home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 517a.lha / FontManipulatorForDtp_v2 / source / mkbmap / mkbmap.c < prev    next >
C/C++ Source or Header  |  1991-06-09  |  29KB  |  965 lines

  1. /* Amiga bitmapped font builder.  File "mkbmap.c".
  2.  * (C) Adrian Aylward 1991
  3.  *
  4.  * You may freely copy, use, and modify this file.
  5.  *
  6.  * This program prints builds an Amiga format bitmapped screen font file
  7.  * from the corresponding PostScript font, using post.library. It is totally
  8.  * Amiga specific.
  9.  *
  10.  * The program was tested using Lattice C V5.05.  It has various Lattice
  11.  * dependencies.
  12.  *
  13.  * This is version 1.2.
  14.  */
  15.  
  16. # include <dos.h>
  17. # include <exec/exec.h>
  18. # include <libraries/diskfont.h>
  19. # include <proto/diskfont.h>
  20. # include <proto/dos.h>
  21. # include <proto/exec.h>
  22. # include <string.h>
  23. # include <stdarg.h>
  24. # include <stdio.h>
  25.  
  26. # include "postlib.h"
  27.  
  28. # undef  POSTVERNO
  29. # define POSTVERNO 15  /* We need post.library version 1.5+ */
  30.  
  31. /* The following definitions appear to be missing from the Lattice headers */
  32.  
  33. # ifdef LATTICE
  34. extern struct FontContentsHeader *NewFontContents(BPTR lock, char *name);
  35. extern void DisposeFontContents(struct FontContentsHeader *fc);
  36.  
  37. # pragma libcall DiskfontBase NewFontContents     2a   9802 ; d0 = (a0, a1)
  38. # pragma libcall DiskfontBase DisposeFontContents 30    901 ;      (a1)
  39. # endif
  40.  
  41. /* Assembler routines */
  42.  
  43. extern void insertftrap(void);
  44. extern void deleteftrap(void);
  45.  
  46. /* Object module hunks */
  47.  
  48. # define Hunk_Header  0x3F3
  49. # define Hunk_Code    0x3E9
  50. # define Hunk_Reloc32 0x3EC
  51. # define Hunk_End     0x3F2
  52.  
  53. # define MOVFFD0RTS   0x70FF4E75
  54.  
  55. /* External data (initialised to zero) */
  56.  
  57. char *argbmapfile, *argfontname, *argpointsizes;
  58. char *argstartupfile, *argencodingfile;
  59. int optfontencoding, optnew;
  60. int optmonospaced, optbold, optitalic, opttrace;
  61. int optden, optxden, optyden, optbaseline, optwidth, optclip;
  62. int pointc, pointn, pointv[100];
  63.  
  64. int retcode;
  65.  
  66. int arec;
  67.  
  68. struct library *PSbase;
  69. struct PSparm parm;
  70.  
  71. APTR functab[10];
  72.  
  73. int ftrapset;
  74.  
  75. int pointsize;
  76. char namebuf[100 + 5];
  77. char psstring[200];
  78. int pserror;
  79.  
  80. int lochar, hichar;
  81. int baseline, nomwidth, nomcount;
  82.  
  83. int llx[256], lly[256], urx[256], ury[256];
  84.  
  85. int cposx, cposy;
  86.  
  87. void *fontmem;
  88. int baselen;
  89. int maxfontlen, maxcharlen, maxmodulo, maxwidth; 
  90. int actfontlen, actcharlen, actmodulo, actwidth; 
  91. int hunklen, hunknum, *hunkptr;
  92.  
  93. BPTR fdlock, cdlock, newfh;
  94.  
  95. struct FontContentsHeader *fcheader;
  96.  
  97. struct DiskFontHeader *dfheader;
  98.  
  99. char *chardata;
  100. short *charloc, *charspace, *charkern;
  101.  
  102. /* Routines */
  103.  
  104. extern int strtoint(char **sp, int *ip);
  105. extern char *buildfnumname(char *nbuf, char *name, int num);
  106. extern char *buildfdirname(char *nbuf, char *name, int type);
  107. extern void pstrace(char *format, ...);
  108. extern void pssintf(char *format, ...);
  109. extern void __saveds setbbox(int ch, int lx, int ly, int rx, int uy);
  110. extern void __saveds setcpos(int cpx, int cpy);
  111.  
  112. /* Main program */
  113.  
  114. void main(int argc, char **argv)
  115. {   char *s, *t;
  116.     int *ip, i, l, ch;
  117.     int y1, y2, z1, z2, zz, ww;
  118.  
  119.     /* Parse arguments.  No workbench startup */
  120.  
  121.     optxden = optyden = 75;
  122.     optbaseline = optwidth = -1;
  123.     lochar = 32;
  124.     hichar = 255;
  125.  
  126.     if (argc == 0) goto tidyexit;
  127.     argv++;
  128.     argc--;
  129.     if (argc == 0 || (argc == 1 && strcmp(*argv, "?") == 0)) goto query;
  130.  
  131.     while (argc)
  132.     {   s = *argv;
  133.         if (*s != '-') break;
  134.         argv++;
  135.         argc--;
  136.         if (strcmp(s, "--") == 0) break;
  137.         s++;
  138.         for (;;)
  139.         {   ch = *s++;
  140.             if (ch == 0) break;
  141.             switch (ch)
  142.             {   case 'S': case 's':
  143.                     if (argc == 0) goto badargs;
  144.                     argstartupfile = *argv++;
  145.                     argc--;
  146.                     continue;
  147.  
  148.                 case 'E': case 'e':
  149.                     if (argc == 0) goto badargs;
  150.                     argencodingfile = *argv++;
  151.                     argc--;
  152.                     continue;
  153.  
  154.                 case 'F': case 'f':
  155.                     optfontencoding = 1;
  156.                     continue;
  157.  
  158.                 case 'N': case 'n':
  159.                     optnew = 1;
  160.                     continue;
  161.  
  162.                 case 'D': case 'd':
  163.                     ip = &optden;
  164.                     break;
  165.  
  166.                 case 'X': case 'x':
  167.                     ip = &optxden;
  168.                     break;
  169.  
  170.                 case 'Y': case 'y':
  171.                     ip = &optyden;
  172.                     break;
  173.  
  174.                 case 'Z': case 'z':
  175.                     ip = &optbaseline;
  176.                     break;
  177.  
  178.                 case 'W': case 'w':
  179.                     ip = &optwidth;
  180.                     break;
  181.  
  182.                 case 'L': case 'l':
  183.                     ip = &lochar;
  184.                     break;
  185.  
  186.                 case 'H': case 'h':
  187.                     ip = &hichar;
  188.                     break;
  189.  
  190.                 case 'C': case 'c':
  191.                     optclip = 1;
  192.                     continue;
  193.  
  194.                 case 'M': case 'm':
  195.                     optmonospaced = 1;
  196.                     continue;
  197.  
  198.                 case 'B': case 'b':
  199.                     optbold = 1;
  200.                     continue;
  201.  
  202.                 case 'I': case 'i':
  203.                     optitalic = 1;
  204.                     continue;
  205.  
  206.                 case 'T': case 't':
  207.                     opttrace = 1;
  208.                     continue;
  209.  
  210.                 default:
  211.                     fprintf(stderr, "mkbmap: unknown option \"-%c\"", ch);
  212.                     goto badusage;
  213.             }
  214.             if (!strtoint(&s, ip)) goto badargs;
  215.             if (ip == &optden) optxden = optyden = optden;
  216.         }
  217.  
  218.         if (*s == '-' && *(s + 1) == 0) break;
  219.     }
  220.  
  221.     if (lochar > hichar || hichar > 255)
  222.     {   fprintf(stderr, "mkbmap: LoChar/HiChar out of range "
  223.                                 "(0 <= Lo <= Hi <= 255)\n");
  224.         goto errorexit;
  225.     }
  226.  
  227.     if (argc != 1 && argc != 3) goto badargs;
  228.     argbmapfile = argv[0];
  229.     if (argc == 3)
  230.     {   argfontname = argv[1];
  231.         argpointsizes = argv[2];
  232.  
  233.         s = argpointsizes;
  234.         while (*s)
  235.         {   i = 0;
  236.             for (;;)
  237.             {   ch = *s;
  238.                 if (ch == 0) break;
  239.                 s++;
  240.                 if (ch == ',') break;
  241.                 if (ch >= '0' && ch <= '9')
  242.                     i = i * 10 + (ch - '0');
  243.                 else
  244.                     goto badargs;
  245.             }
  246.             if (i != 0)
  247.             {   if (i < 5 || i > 500)
  248.                 {   fprintf(stderr, "mkbmap: point size %d out of range "
  249.                                             "(5 - 500)\n", pointsize);
  250.                     goto errorexit;
  251.                 }
  252.                 if (pointc == 100) goto badargs;
  253.                 pointv[pointc++] = i;
  254.             }
  255.         }
  256.     }
  257.  
  258.     if (pointc == 0) goto newfont;
  259.  
  260.     if (argencodingfile == NULL) argencodingfile = "PSFonts:encoding.ps";
  261.     if (argstartupfile  == NULL) argstartupfile  = "PSFonts:init.ps";
  262.  
  263.     /* Initialise the PostScript library */
  264.  
  265.     pstrace("%% Opening PostScript library\n");
  266.     PSbase = OpenLibrary("post.library", POSTVERNO);
  267.     if (PSbase == NULL)
  268.     {   fprintf(stderr, "mkbmap: can't open post.library (V15+)\n");
  269.         goto errorexit;
  270.     }
  271.  
  272.     pstrace("%% Initialising PostScript activation\n");
  273.     parm.page.buf[0] = namebuf;
  274.     parm.page.len = 100;
  275.     parm.page.depth = 1;
  276.     parm.page.xoff = 0;
  277.     parm.page.yoff = 0;
  278.     parm.page.xbytes = 10;
  279.     parm.page.xsize = 80;
  280.     parm.page.ysize = 10;
  281.     parm.page.ybase = 0;
  282.     parm.page.yheight = 10;
  283.     parm.page.xden = 72;
  284.     parm.page.yden = 72;
  285.     parm.page.ydir = -1;
  286.     parm.memvlen = 20000;
  287.     parm.memflen = 10000;
  288.     parm.memllen = defmemllen;
  289.     parm.memhlen = minmemhlen;
  290.     parm.infh = Input();
  291.     parm.outfh = Output();
  292.     parm.errfh = Output();
  293.     parm.funcmax = 2;
  294.     functab[0] = (APTR) setbbox;
  295.     functab[1] = (APTR) setcpos;
  296.     parm.functab = functab;
  297.     insertftrap();
  298.     ftrapset = 1;
  299.     arec = PScreateact(&parm);
  300.     if (arec == 0)
  301.     {   fprintf(stderr, "mkbmap: post.library can't get memory\n");
  302.         goto errorexit;
  303.     }
  304.     if ((unsigned) arec <= errmax)
  305.     {   pserror = arec;
  306.         arec = 0;
  307.         goto pserror;
  308.     }
  309.  
  310.     /* Load the startup file */
  311.  
  312.     pstrace("%% Loading startup file\n");
  313.     pssintf("(%.100s) run clear\n", argstartupfile);
  314.  
  315.     /* Load the encoding file */
  316.  
  317.     if (optfontencoding == 0)
  318.     {   pstrace("% Loading encoding file\n");
  319.         pssintf("/encoding StandardEncoding 256 array copy def\n");
  320.         pssintf("[ (%.100s) run ] aload length 2 idiv\n", argencodingfile);
  321.         pssintf("{ encoding 3 1 roll put } repeat\n");
  322.     }
  323.  
  324.     /* Load the font.  Make sure we don't get a substitute */
  325.  
  326.     pstrace("%% Loading font\n");
  327.     pssintf("/fontname /%.100s def\n", argfontname);
  328.     pssintf("fontname findfont pop\n");
  329.     pssintf("/font fontname .findfont def\n");
  330.  
  331.     /* Encode the font */
  332.  
  333.     pstrace("%% Encoding font\n");
  334.     pssintf("/newfont font maxlength dict def\n");
  335.     pssintf("font\n"
  336.             "{ exch dup /FID ne "
  337.             "{ exch newfont 3 1 roll put } { pop pop } ifelse }\n"
  338.             "forall\n");
  339.     if (optfontencoding == 0)
  340.            pssintf("newfont /Encoding encoding put\n");
  341.     pssintf("/_%.100s newfont definefont pop\n", argfontname);
  342.     if (pserror != 0) goto pserror;
  343.  
  344.     pstrace("%% LoChar = %d; HiChar = %d\n", lochar, hichar);
  345.  
  346.     /* Determine the bounding boxes for all the characters */
  347.  
  348.     pstrace("%% Generating bounding boxes\n");
  349.     pssintf("/cstr 1 string def\n");
  350.     pssintf("newfont 1000 scalefont setfont\n");
  351.     pssintf("%d 1 %d\n"
  352.             "{ /i exch def cstr 0 i put null i\n"
  353.             "  0 0 moveto cstr false charpath pathbbox newpath\n"
  354.             "  4 { round cvi 4 1 roll } repeat\n"
  355.             "  5 0 callextfunc\n"
  356.             "} for\n", lochar, hichar);
  357.     if (pserror != 0) goto pserror;
  358.  
  359.     /* Position the baseline, if we have not set it explicitly */
  360.  
  361.     if (optbaseline == -1)
  362.     {
  363.         /* This is what we have room for */
  364.  
  365.         zz = (1000 * 72) / optyden;
  366.  
  367.         /* Calculate the lower and upper limits of the whole character set */
  368.  
  369.         z1 = z2 = 0;
  370.         for (i = 0; i <= 255 ; i++)
  371.         {   if (lly[i] < z1) z1 = lly[i];
  372.             if (ury[i] > z2) z2 = ury[i];
  373.         }
  374.         if (z2 == z1)
  375.         {   fprintf(stderr, "mkbmap: all characters in the font are null\n");
  376.             goto errorexit;
  377.         }
  378.  
  379.         /* If we have room for everything, or the font has a non-standard
  380.          * character set, set the baseline in proportion to the relative
  381.          * sizes of the ascenders and descenders */
  382.  
  383.         optbaseline = (1000 * (-z1) + (z2 - z1) / 2) / (z2 - z1);
  384.  
  385.         /* Otherwise, for fonts with standard character sets, calculate the
  386.          * limits of the alphabet.  If we have room for that then leave just
  387.          * enough room for the descenders, or else set the baseline
  388.          * proportionately */
  389.  
  390.         if (z2 - z1 > zz && optfontencoding == 0)
  391.         {   y1 = y2 = 0;
  392.             for (i = 'A'; i <= 'Z' ; i++)
  393.             {   if (lly[i] < y1) y1 = lly[i];
  394.                 if (ury[i] > y2) y2 = ury[i];
  395.             }
  396.             for (i = 'a'; i <= 'z' ; i++)
  397.             {   if (lly[i] < y1) y1 = lly[i];
  398.                 if (ury[i] > y2) y2 = ury[i];
  399.             }
  400.             if (y2 - y1 <= zz)
  401.                 optbaseline = (1000 * (-y1) + zz / 2) / zz;
  402.             else
  403.                 optbaseline = (1000 * (-y1) + (y2 - y1) / 2) / (y2 - y1);
  404.         }
  405.         pstrace("%% Baseline set at %d/1000 of the pixel height\n",
  406.                 optbaseline);
  407.     }
  408.  
  409.     /* Validate the font file name and create the font subdirectory */
  410.  
  411.     if (buildfdirname(namebuf, argbmapfile, 0) == NULL)
  412.     {   fprintf(stderr, "mkbmap: bmap file has no directory path\n");
  413.         goto errorexit;
  414.     }
  415.     if (optnew)
  416.     {   fdlock = CreateDir(namebuf);
  417.         if (fdlock)
  418.         {   UnLock(fdlock);
  419.             fdlock = 0;
  420.         }
  421.     }
  422.  
  423.     /* Loop through all the point sizes */
  424.  
  425.     for (pointn = 0; pointn < pointc; pointn++)
  426.     {   if (SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto broken;
  427.  
  428.         pointsize = pointv[pointn];
  429.         pstrace("%% Point size %d\n", pointsize);
  430.         baseline = (pointsize * optbaseline + 500) / 1000;
  431.         if (baseline < 0) baseline = 0;
  432.         if (baseline > pointsize - 1) baseline = pointsize - 1;
  433.  
  434.  
  435.         /* Build the bitmapped font in memory.  Estimate the maximum
  436.          * possible width of the bitmap from the total widths of the
  437.          * bounding boxes, allowing 2 extra pixels per character for
  438.          * rounding and stem alignment.  Calculate the mamimum font
  439.          * length, allocate the memory, and initialise the headers */
  440.  
  441.         baselen = 4 + sizeof (struct DiskFontHeader) +
  442.                       8 * (hichar - lochar + 2);
  443.  
  444.         maxwidth = 0;
  445.         for (ch = lochar; ch <= hichar ; ch++)
  446.             maxwidth +=
  447.                 ((urx[ch] - llx[ch]) * pointsize * optxden) / 72000 + 2;
  448.         maxmodulo = ((maxwidth + 15) >> 3) & ~1;
  449.         maxcharlen = maxmodulo * pointsize;
  450.         maxfontlen = baselen + maxcharlen + 2 + 76;
  451.  
  452.         fontmem = AllocMem(maxfontlen, MEMF_PUBLIC|MEMF_CLEAR);
  453.         if (fontmem == NULL)
  454.         {   fprintf(stderr, "mkbmap: can't get font memory\n");
  455.             goto errorexit;
  456.         }
  457.  
  458.         hunkptr   = fontmem;
  459.         dfheader  = (void *) &hunkptr[9];
  460.         charloc   = (void *) &dfheader[1];
  461.         charspace = (void *) &charloc[(hichar - lochar + 2) * 2];
  462.         charkern  = (void *) &charspace[hichar - lochar + 2];
  463.         chardata  = (void *) &charkern[hichar - lochar + 2];
  464.  
  465.         /* Set up the bitmap to render the characters */
  466.  
  467.         pstrace("%% Rendering bitmaps\n");
  468.         parm.page.buf[0] = (char *) chardata;
  469.         parm.page.len = maxcharlen;
  470.         parm.page.depth = 1;
  471.         parm.page.xoff = 0;
  472.         parm.page.yoff = 0;
  473.         parm.page.xbytes = maxmodulo;
  474.         parm.page.xsize = maxwidth;
  475.         parm.page.ysize = pointsize;
  476.         parm.page.ybase = 0;
  477.         parm.page.yheight = pointsize;
  478.         PSsetdevice(arec, &parm.page);
  479.  
  480.         pssintf("initmatrix\n");
  481.         pssintf("/xscale %d %d mul 72 div def\n", pointsize, optxden);
  482.         pssintf("/yscale %d %d mul 72 div def\n", pointsize, optyden);
  483.         pssintf("newfont [ xscale 0 0 yscale 0 0 ] makefont setfont\n");
  484.  
  485.         actwidth = 0;
  486.         nomwidth = 0;
  487.         nomcount = 0;
  488.  
  489.         /* Loop to render each character.  We estimate the bounds of the
  490.          * characters conservatively (hinting any shift them a little) and
  491.          * trim the bitmap if possible.  We clip on the left, so any part
  492.          * of the character projecting to the left is truncated, and does
  493.          * not overwrite the previous one.  We erase the character cell so
  494.          * it does not matter if the clipping of the right of the previous
  495.          * character was not complete.  We render the portiona above and
  496.          * below the baseline separately, so they can be indepently scaled
  497.          * to fit */
  498.  
  499.         for (ch = lochar; ch <= hichar; ch++)
  500.         {   z1 = (llx[ch] * pointsize * optxden - 41000) / 72000;
  501.             z2 = (urx[ch] * pointsize * optxden + 41000) / 72000;
  502.             if (optclip != 0) if (z1 < 0) z1 = 0;
  503.             pssintf("cstr 0 %d put\n", ch);
  504.             pssintf("%d %d moveto\n", actwidth, baseline);
  505.             pssintf("gsave %d 0 rlineto 0 %d rlineto "
  506.                     "-%d 0 rlineto closepath clip\n",
  507.                     z2 - z1, -baseline, z2 - z1);
  508.             pssintf("1 setgray fill 0 setgray\n");
  509.             pssintf("%d %d moveto ", actwidth - z1, baseline);
  510.             y1 = ((-lly[ch]) * pointsize * optxden) / 72;
  511.             y2 = baseline * 1000;
  512.             if (y1 > y2)
  513.                 pssintf("1 %d %d div scale\n", y2, y1);
  514.             pssintf("cstr show\n"
  515.                     "grestore\n");
  516.             pssintf("gsave %d 0 rlineto 0 %d rlineto "
  517.                     "-%d 0 rlineto closepath clip\n",
  518.                     z2 - z1, pointsize - baseline, z2 - z1);
  519.             pssintf("1 setgray fill newpath 0 setgray\n");
  520.             pssintf("%d %d moveto ", actwidth - z1, baseline);
  521.             y1 = (ury[ch] * pointsize * optxden) / 72;
  522.             y2 = (pointsize - baseline) * 1000;
  523.             if (y1 > y2)
  524.                 pssintf("1 %d %d div scale\n", y2, y1);
  525.             pssintf("cstr show\n"
  526.                     "null currentpoint 2 { round cvi exch } repeat "
  527.                     "2 1 callextfunc\n"
  528.                     "grestore\n");
  529.             ww = cposx - actwidth;
  530.             zz = z2 - z1;
  531.             if (optclip != 0) if (zz > ww) zz = ww;
  532.             i = ch - lochar;
  533.             charloc[i * 2] = actwidth;
  534.             charloc[i * 2 + 1] = zz;
  535.             charspace[i] = ww;
  536.             charkern[i] = z1;
  537.             actwidth += zz;
  538.             if (lly[ch] != ury[ch])
  539.             {   nomwidth += z1 + ww;
  540.                 nomcount++;
  541.             }
  542.             if (SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  543.                 goto broken;
  544.         }
  545.  
  546.         if (pserror != 0) goto pserror;
  547.  
  548.         /* If we have not explicitly set the nominal character width,
  549.          * calculate it as the average width of the non-null characters
  550.          * we have generated */
  551.  
  552.         if (optwidth == -1)
  553.         {   if (nomcount != 0)
  554.                 nomwidth = (nomwidth + nomcount / 2) / nomcount;
  555.         }
  556.         else
  557.             nomwidth = (optwidth * pointsize * optxden + 36000) / 72000;
  558.  
  559.         /* We now know the actual width, so we can calculate the actual
  560.          * modulo and file lengths.  Then we must reformat the bitmap to
  561.          * the new width */
  562.  
  563.         if (actwidth > maxwidth)
  564.         {   fprintf(stderr, "mkbmap: width estimate exceeded\n");
  565.             goto errorexit;
  566.         }
  567.         actmodulo = ((actwidth + 15) >> 3) & ~1;
  568.         actcharlen = actmodulo * pointsize;
  569.         hunklen = baselen + actcharlen;
  570.         if (hunklen & 2) hunklen += 2;
  571.         hunknum = hunklen >> 2;
  572.         actfontlen = hunklen + 76;
  573.  
  574.         i = 1;
  575.         s = chardata + maxmodulo;
  576.         t = chardata + actmodulo;
  577.         while (i < pointsize)
  578.         {   l = actmodulo;
  579.             while (l--) *t++ = *s++;
  580.             i++;
  581.             s += (maxmodulo - actmodulo);
  582.         }
  583.  
  584.         /* Finish the bitmapped font.  Write it out to the file */
  585.  
  586.         buildfdirname(namebuf, argbmapfile, 2);
  587.  
  588.         hunkptr[0] = Hunk_Header;
  589.         hunkptr[1] = 0;
  590.         hunkptr[2] = 1;
  591.         hunkptr[3] = 0;
  592.         hunkptr[4] = 0;
  593.         hunkptr[5] = hunknum;
  594.         hunkptr[6] = Hunk_Code;
  595.         hunkptr[7] = hunknum;
  596.         hunkptr += 8;
  597.  
  598.         hunkptr[0] = MOVFFD0RTS;
  599.  
  600.         dfheader->dfh_DF.ln_Type = NT_FONT;
  601.         dfheader->dfh_DF.ln_Name = (char *) 0x0000001A;
  602.         dfheader->dfh_FileID = DFH_ID;
  603.         strncpy((char *)&dfheader->dfh_Name, namebuf, MAXFONTNAME);
  604.         dfheader->dfh_TF.tf_Message.mn_Node.ln_Type = NT_FONT;
  605.         dfheader->dfh_TF.tf_Message.mn_Node.ln_Name = (char *) 0x0000001A;
  606.         dfheader->dfh_TF.tf_Message.mn_Length = hunklen - 58;
  607.         dfheader->dfh_TF.tf_YSize = pointsize;
  608.         dfheader->dfh_TF.tf_Style =
  609.             (optbold ? FSF_BOLD : 0) | (optitalic ? FSF_ITALIC : 0);
  610.         dfheader->dfh_TF.tf_Flags =
  611.             (optmonospaced ? 0 : FPF_PROPORTIONAL) | FPF_DESIGNED;
  612.         dfheader->dfh_TF.tf_XSize = nomwidth;
  613.         dfheader->dfh_TF.tf_Baseline = pointsize - baseline - 1;
  614.         dfheader->dfh_TF.tf_BoldSmear = pointsize / 20 + 1;
  615.         dfheader->dfh_TF.tf_LoChar = lochar;
  616.         dfheader->dfh_TF.tf_HiChar = hichar;
  617.         dfheader->dfh_TF.tf_CharData =
  618.             (APTR) ((char *) chardata  - (char *) hunkptr);
  619.         dfheader->dfh_TF.tf_Modulo = actmodulo;
  620.         dfheader->dfh_TF.tf_CharLoc =
  621.             (APTR) ((char *) charloc   - (char *) hunkptr);
  622.         dfheader->dfh_TF.tf_CharSpace =
  623.             (APTR) ((char *) charspace - (char *) hunkptr);
  624.         dfheader->dfh_TF.tf_CharKern =
  625.             (APTR) ((char *) charkern  - (char *) hunkptr);
  626.  
  627.         hunkptr += hunknum;
  628.  
  629.         hunkptr[0] = Hunk_Reloc32;
  630.         hunkptr[1] = 6;
  631.         hunkptr[2] = 0;
  632.         hunkptr[3] = 0x0000006A;
  633.         hunkptr[4] = 0x00000066;
  634.         hunkptr[5] = 0x00000062;
  635.         hunkptr[6] = 0x0000005C;
  636.         hunkptr[7] = 0x00000044;
  637.         hunkptr[8] = 0x0000000E;
  638.         hunkptr[9] = 0;
  639.         hunkptr[10] = Hunk_End;
  640.  
  641.         pstrace("%% Writing bmap file\n");
  642.         if (buildfnumname(namebuf, argbmapfile, pointsize) == NULL)
  643.         {   fprintf(stderr, "mkbmap: bmap file name too long\n");
  644.             goto errorexit;
  645.         }
  646.         newfh = Open(namebuf, MODE_NEWFILE);
  647.         if (newfh == NULL)
  648.         {   fprintf(stderr, "mkbmap: can't open bmap file %s\n", namebuf);
  649.             goto errorexit;
  650.         }
  651.         i = Write(newfh, (UBYTE *) fontmem, actfontlen);
  652.         Close(newfh);
  653.         if (i == -1)
  654.         {   fprintf(stderr, "mkbmap: error writing bmap file %s\n", namebuf);
  655.             goto errorexit;
  656.         }
  657.     }
  658.  
  659.     /* Update font contents file */
  660.  
  661. newfont:
  662.     if (optnew)
  663.     {   pstrace("%% Updating font contents file\n");
  664.         buildfdirname(namebuf, argbmapfile, 1);
  665.         fdlock = Lock(namebuf, SHARED_LOCK);
  666.         if (fdlock == NULL)
  667.         {   fprintf(stderr, "mkbmap: can't lock font directory %s\n",
  668.                             namebuf);
  669.             goto errorexit;
  670.         }
  671.         buildfdirname(namebuf, argbmapfile, 2);
  672.         strcat(namebuf, ".font");
  673.         DiskfontBase = OpenLibrary("diskfont.library", 34);
  674.         if (DiskfontBase) fcheader = NewFontContents(fdlock, namebuf);
  675.         if (fcheader == NULL)
  676.         {   fprintf(stderr, "mkbmap: can't create new font contents %s\n",
  677.                     namebuf);
  678.             goto errorexit;
  679.         }
  680.         if (fcheader->fch_NumEntries == 0)
  681.         {   fprintf(stderr, "mkbmap: font %s directory contains no fonts\n",
  682.                     namebuf);
  683.             retcode = 10;
  684.             goto tidyexit;
  685.         }
  686.  
  687.         /* Swap to the font directory, update the file, and swap back */
  688.  
  689.         cdlock = CurrentDir(fdlock);
  690.         newfh = Open(namebuf, MODE_NEWFILE);
  691.         if (newfh)
  692.         {   i = Write(newfh, (UBYTE *)fcheader,
  693.                     sizeof (struct FontContentsHeader) +
  694.                     sizeof (struct FontContents) * fcheader->fch_NumEntries);
  695.             Close(newfh);
  696.         }
  697.         CurrentDir(cdlock);
  698.         if      (newfh == NULL)
  699.         {   fprintf(stderr, "mkbmap: can't open font contents file %s\n",
  700.                     namebuf);
  701.             goto errorexit;
  702.         }
  703.         else if (i == -1)
  704.         {   fprintf(stderr, "mkbmap: error writing font contents file %s\n",
  705.                     namebuf);
  706.             goto errorexit;
  707.         }
  708.  
  709.         /* Tidy up */
  710.  
  711.         DisposeFontContents(fcheader);
  712.         fcheader = NULL;
  713.         CloseLibrary(DiskfontBase);
  714.         DiskfontBase = NULL;
  715.         UnLock(fdlock);
  716.         fdlock = NULL;
  717.     }
  718.  
  719.     /* All done */
  720.  
  721.     pstrace("%% All done\n");
  722.     goto tidyexit;
  723.  
  724.     /* Argument errors and usage query */
  725.  
  726. query:
  727.     fprintf(stderr, "Bitmap font generator.  MkBmap version 1.2\n"
  728.                     "Makes Amiga bitmapped fonts from PostScript fonts\n"
  729.                     "\n"
  730.                     "  Usage:\n"
  731.                     "\n"
  732.                     "    mkbmap -options bmapfile fontname nn,nn,...\n"
  733.                     "\n"
  734.                     "      -s startupfile  Startup file name\n"
  735.                     "      -e encodingfile Encoding file name\n"
  736.                     "      -f              Font specific encoding\n"
  737.                     "      -n              Make new .font contents\n");
  738.     fprintf(stderr, "      -dnnn           Density: x and y (dpi)\n"
  739.                     "      -xnnn           Density: x (dpi)\n"
  740.                     "      -ynnn           Density: y (dpi)\n"
  741.                     "      -znnn           Baseline (1/1000)\n"
  742.                     "      -wnnn           Width    (1/1000)\n"
  743.                     "      -lnnn           LoChar\n"
  744.                     "      -hnnn           Hichar\n"
  745.                     "      -c              Clip to character width\n"
  746.                     "      -m              Monospaced\n"
  747.                     "      -b              Bold\n"
  748.                     "      -i              Italic\n"
  749.                     "      -t              Trace (for debugging)\n"
  750.                     "\n"
  751.                     "  For example:\n"
  752.                     "\n"
  753.                     "    mkbmap -n fonts:Times/* Times-Roman 10,12,14\n");
  754.     goto tidyexit;
  755.  
  756. badargs:
  757.     fprintf(stderr, "mkbmap: arguments bad, or value missing");
  758. badusage:
  759.     retcode = 20;
  760.     fprintf(stderr, ".  Usage:\n"
  761.                     "    mkbmap -options bmapfile fontname nn,nn,...\n");
  762.     goto tidyexit;
  763.  
  764.     /* PostScript library error */
  765.  
  766. pserror:
  767.     fprintf(stderr, "mkbmap: post.library interpreter error\n");
  768.     goto errorexit;
  769.  
  770.     /* Tidy up and exit */
  771.  
  772. broken:
  773.     fprintf(stderr, "mkbmap: *** Break\n");
  774.     retcode = 10;
  775.     goto tidyexit;
  776.  
  777. errorexit:
  778.     retcode = 20;
  779.  
  780. tidyexit:
  781.     if (ftrapset)
  782.     {   deleteftrap();
  783.         ftrapset = 0;
  784.     }
  785.  
  786.     if (arec) PSdeleteact(arec);
  787.     if (PSbase) CloseLibrary(PSbase);
  788.  
  789.     if (fontmem) FreeMem(fontmem, maxfontlen);
  790.  
  791.     if (fcheader) DisposeFontContents(fcheader);
  792.     if (DiskfontBase) CloseLibrary(DiskfontBase);
  793.     if (fdlock) UnLock(fdlock);
  794.  
  795.     exit(retcode);
  796. }
  797.  
  798. /* String to integer conversion; digits only, with error check */
  799.  
  800. int strtoint(char **sp, int *ip)
  801. {   char *s = *sp;
  802.     int i = 0;
  803.     int ch;
  804.     for (;;)
  805.     {   ch = *s;
  806.         if (ch < '0' || ch > '9') break;
  807.         i = i * 10 + (ch - '0');
  808.         s++;
  809.     }
  810.     if (s == *sp)
  811.         return 0;
  812.     else
  813.     {   *sp = s;
  814.         *ip = i;
  815.         return 1;
  816.     }
  817. }
  818.  
  819. /* Build the bitmap font file name.  Copy it, replacing "*" by the point
  820.  * size.  Then scan it backwards replacing "?" by digits */
  821.  
  822. char *buildfnumname(char *nbuf, char *name, int num)
  823. {   char number[10];
  824.     int numlen, i, j, k, ch;
  825.     numlen = 0;
  826.     while (num)
  827.     {   number[numlen++] = num % 10 + '0';
  828.         num /= 10;
  829.     }
  830.     i = j = 0;
  831.     for (;;)
  832.     {   if (j > 100) return NULL;
  833.         ch = name[i++];
  834.         if (ch == '*')
  835.         {   k = numlen;
  836.             while (k--) nbuf[j++] = number[k];
  837.         }
  838.         else
  839.            nbuf[j++] = ch;
  840.         if (ch == 0) break;
  841.     }
  842.     k = 0;
  843.     while (--j)
  844.     {   if (nbuf[j] == '?')
  845.             nbuf[j] = (k < numlen) ? number[k++] : '0';
  846.     }
  847.     return nbuf;
  848. }
  849.  
  850. /* Build the font file/directory name.  We copy it, striping off the last
  851.  * two components:
  852.  *
  853.  * type = 0: fontdir/fontname/* => fontdir/fontname
  854.  * type = 1: fontdir/fontname/* => fontdir
  855.  * type = 2: fontdir/fontname/* => fontname
  856.  *
  857.  *       (or fontdir:fontname/* => ...)
  858.  */
  859.  
  860. char *buildfdirname(char *nbuf, char *name, int type)
  861. {   int i, j, k;
  862.     i = strlen(name);
  863.     for (;;)
  864.     {   if (i == 0) return NULL;
  865.         i--;
  866.         if (name[i] == ':') return NULL;
  867.         if (name[i] == '/') break;
  868.     }
  869.     j = i;
  870.     for (;;)
  871.     {   if (j == 0) return NULL;
  872.         j--;
  873.         if (name[j] == ':')
  874.         {   k = j = j + 1;
  875.             break;
  876.         }
  877.         if (name[j] == '/')
  878.         {   k = j;
  879.             j = j + 1;
  880.             break;
  881.         }
  882.     }
  883.     if (k == 0) return NULL;
  884.     if (i >= 100) return NULL;
  885.     if      (type == 1)
  886.         i = k;
  887.     else if (type == 2)
  888.     {   name += j;
  889.         i -= j;
  890.     }
  891.     memcpy(nbuf, name, i);
  892.     nbuf[i] = 0;
  893.     return nbuf;
  894. }
  895.  
  896. /* Trace output */
  897.  
  898. void pstrace(char *format, ...)
  899. {   va_list ap;
  900.     if (pserror != 0) return;
  901.     if (opttrace)
  902.     {   va_start(ap, format);
  903.         vfprintf(stdout, format, ap);
  904.         fflush(stdout);
  905.         va_end(ap);
  906.     }
  907. }
  908.  
  909. /* Interpret postscript string */
  910.  
  911. void pssintf(char *format, ...)
  912. {   va_list ap;
  913.     if (pserror != 0) return;
  914.     va_start(ap, format);
  915.     if (opttrace)
  916.     {   vfprintf(stdout, format, ap);
  917.         fflush(stdout);
  918.     }
  919.     vsprintf(psstring, format, ap);
  920.     pserror = PSintstring(arec, psstring, -1, PSFLAGSTRING)
  921.     va_end(ap);
  922. }
  923.  
  924. /* Set character bounding box */
  925.  
  926. void __saveds setbbox(int ch, int lx, int ly, int rx, int uy)
  927. {   llx[ch] = lx;
  928.     lly[ch] = ly;
  929.     urx[ch] = rx;
  930.     ury[ch] = uy;
  931. }
  932.  
  933. /* Set current point */
  934.  
  935. void __saveds setcpos(int cpx, int cpy)
  936. {   cposx = cpx;
  937.     cposy = cpy;
  938. }
  939.  
  940. /* Signal an interrupt */
  941.  
  942. void __saveds sigint()
  943. {   PSsignalint(arec, 1);
  944. }
  945.  
  946. /* Signal a floating point error */
  947.  
  948. void __saveds sigfpe()
  949. {   PSsignalfpe(arec);
  950. }
  951.  
  952. /* Dummy stub routine */
  953.  
  954. void stub(void)
  955. {   return;
  956. }
  957.  
  958. /* Dummy check abort routine */
  959.  
  960. void chkabort(void)
  961. {   return;
  962. }
  963.  
  964. /* End of file "mkbmap.c" */
  965.