home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / fonts / lib / font / bitmap / bdfread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  25.9 KB  |  909 lines

  1. /************************************************************************
  2. Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted,
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ************************************************************************/
  24.  
  25. /* $XConsortium: bdfread.c,v 1.13 92/05/12 18:07:40 gildea Exp $ */
  26.  
  27. #include <ctype.h>
  28. #include "fontfilest.h"
  29. /* use bitmap structure */
  30. #include "bitmap.h"
  31. #include "bdfint.h"
  32.  
  33. #define INDICES 256
  34. #define MAXENCODING 0xFFFF
  35. #define BDFLINELEN  1024
  36.  
  37. extern int  bitmapGetGlyphs(), bitmapGetMetrics();
  38. extern int  bitmapGetBitmaps(), bitmapGetExtents();
  39. void        bdfUnloadFont();
  40. static Bool bdfPadToTerminal();
  41.  
  42. /***====================================================================***/
  43.  
  44. static Bool
  45. bdfReadBitmap(pCI, file, bit, byte, glyph, scan, sizes)
  46.     CharInfoPtr pCI;
  47.     FontFilePtr file;
  48.     int         bit,
  49.                 byte,
  50.                 glyph,
  51.                 scan;
  52.     int         sizes[GLYPHPADOPTIONS];
  53. {
  54.     int         widthBits,
  55.                 widthBytes,
  56.                 widthHexChars;
  57.     int         height,
  58.                 row;
  59.     int         i,
  60.                 inLineLen,
  61.                 nextByte;
  62.     Bool        badbits;
  63.     unsigned char *pInBits,
  64.                *picture,
  65.                *line = NULL;
  66.     char        lineBuf[BDFLINELEN];
  67.  
  68.     widthBits = GLYPHWIDTHPIXELS(pCI);
  69.     height = GLYPHHEIGHTPIXELS(pCI);
  70.  
  71.     widthBytes = BYTES_PER_ROW(widthBits, glyph);
  72.     if (widthBytes * height > 0) {
  73.     picture = (unsigned char *) xalloc(widthBytes * height);
  74.     if (!picture)
  75.         goto BAILOUT;
  76.     } else
  77.     picture = NULL;
  78.     pCI->bits = (char *) picture;
  79.  
  80.     if (sizes) {
  81.     for (i = 0; i < GLYPHPADOPTIONS; i++)
  82.         sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height;
  83.     }
  84.     badbits = FALSE;
  85.     nextByte = 0;
  86.     widthHexChars = BYTES_PER_ROW(widthBits, 1);
  87.  
  88. /* 5/31/89 (ef) -- hack, hack, hack.  what *am* I supposed to do with */
  89. /*        0 width characters? */
  90.  
  91.     for (row = 0; row < height; row++) {
  92.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  93.     if (!line)
  94.         break;
  95.  
  96.     if (widthBits == 0) {
  97.         if ((!line) || (bdfIsPrefix(line, "ENDCHAR")))
  98.         break;
  99.         else
  100.         continue;
  101.     }
  102.     pInBits = line;
  103.     inLineLen = strlen((char *) pInBits);
  104.  
  105.     if (inLineLen & 1) {
  106.         bdfError("odd number of characters in hex encoding\n");
  107.         line[inLineLen++] = '0';
  108.         line[inLineLen] = '\0';
  109.     }
  110.     inLineLen >>= 1;
  111.     i = inLineLen;
  112.     if (i > widthHexChars)
  113.         i = widthHexChars;
  114.     for (; i > 0; i--, pInBits += 2)
  115.         picture[nextByte++] = bdfHexByte(pInBits);
  116.  
  117.     /* pad if line is too short */
  118.     if (inLineLen < widthHexChars) {
  119.         for (i = widthHexChars - inLineLen; i > 0; i--)
  120.         picture[nextByte++] = 0;
  121.     } else {
  122.         unsigned char mask;
  123.  
  124.         mask = 0xff << (8 - (widthBits & 0x7));
  125.         if (mask && picture[nextByte - 1] & ~mask) {
  126.         picture[nextByte - 1] &= mask;
  127.         badbits = TRUE;
  128.         } else if (inLineLen > widthHexChars)
  129.         badbits = TRUE;
  130.     }
  131.  
  132.     if (widthBytes > widthHexChars) {
  133.         i = widthBytes - widthHexChars;
  134.         while (i-- > 0)
  135.         picture[nextByte++] = 0;
  136.     }
  137.     }
  138.  
  139.     if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0))
  140.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  141.  
  142.     if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) {
  143.     bdfError("missing 'ENDCHAR'\n");
  144.     goto BAILOUT;
  145.     }
  146.     if (nextByte != height * widthBytes) {
  147.     bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n",
  148.          nextByte, height, widthBytes);
  149.     goto BAILOUT;
  150.     }
  151.     if (picture != NULL) {
  152.     if (bit == LSBFirst)
  153.         BitOrderInvert(picture, nextByte);
  154.     if (bit != byte) {
  155.         if (scan == 2)
  156.         TwoByteSwap(picture, nextByte);
  157.         else if (scan == 4)
  158.         FourByteSwap(picture, nextByte);
  159.     }
  160.     }
  161.     return (TRUE);
  162. BAILOUT:
  163.     if (picture)
  164.     xfree(picture);
  165.     pCI->bits = NULL;
  166.     return (FALSE);
  167. }
  168.  
  169. /***====================================================================***/
  170.  
  171. static Bool
  172. bdfSkipBitmap(file, height)
  173.     FontFilePtr file;
  174.     int         height;
  175. {
  176.     unsigned char *line;
  177.     int         i = 0;
  178.     char        lineBuf[BDFLINELEN];
  179.  
  180.     do {
  181.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  182.     i++;
  183.     } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height);
  184.  
  185.     if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) {
  186.     bdfError("Error in bitmap, missing 'ENDCHAR'\n");
  187.     return (FALSE);
  188.     }
  189.     return (TRUE);
  190. }
  191.  
  192. /***====================================================================***/
  193.  
  194.  
  195. static Bool
  196. bdfReadCharacters(file, pFont, pState, bit, byte, glyph, scan)
  197.     FontFilePtr file;
  198.     FontPtr     pFont;
  199.     bdfFileState *pState;
  200.     int         bit,
  201.                 byte,
  202.                 glyph,
  203.                 scan;
  204. {
  205.     unsigned char *line;
  206.     register CharInfoPtr ci;
  207.     int         i,
  208.                 ndx,
  209.                 nchars,
  210.                 nignored;
  211.     unsigned int char_row, char_col;
  212.     int         numEncodedGlyphs = 0;
  213.     CharInfoPtr *bdfEncoding[256];
  214.     BitmapFontPtr  bitmapFont;
  215.     BitmapExtraPtr bitmapExtra;
  216.     CARD32     *bitmapsSizes;
  217.     char        lineBuf[BDFLINELEN];
  218.     int         nencoding;
  219.  
  220.     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
  221.     bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
  222.  
  223.     if (bitmapExtra) {
  224.     bitmapsSizes = bitmapExtra->bitmapsSizes;
  225.     for (i = 0; i < GLYPHPADOPTIONS; i++)
  226.         bitmapsSizes[i] = 0;
  227.     } else
  228.     bitmapsSizes = NULL;
  229.  
  230.     bzero(bdfEncoding, sizeof(bdfEncoding));
  231.     bitmapFont->metrics = NULL;
  232.     ndx = 0;
  233.  
  234.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  235.  
  236.     if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) {
  237.     bdfError("bad 'CHARS' in bdf file\n");
  238.     return (FALSE);
  239.     }
  240.     if (nchars < 1) {
  241.     bdfError("invalid number of CHARS in BDF file\n");
  242.     return (FALSE);
  243.     }
  244.     ci = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec));
  245.     if (!ci) {
  246.     bdfError("Couldn't allocate pCI (%d*%d)\n", nchars,
  247.          sizeof(CharInfoRec));
  248.     goto BAILOUT;
  249.     }
  250.     bitmapFont->metrics = ci;
  251.  
  252.     if (bitmapExtra) {
  253.     bitmapExtra->glyphNames = (Atom *) xalloc(nchars * sizeof(Atom));
  254.     if (!bitmapExtra->glyphNames) {
  255.         bdfError("Couldn't allocate glyphNames (%d*%d)\n",
  256.              nchars, sizeof(Atom));
  257.         goto BAILOUT;
  258.     }
  259.     }
  260.     if (bitmapExtra) {
  261.     bitmapExtra->sWidths = (int *) xalloc(nchars * sizeof(int));
  262.     if (!bitmapExtra->sWidths) {
  263.         bdfError("Couldn't allocate sWidth (%d *%d)\n",
  264.              nchars, sizeof(int));
  265.         return FALSE;
  266.     }
  267.     }
  268.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  269.     pFont->info.firstRow = 256;
  270.     pFont->info.lastRow = 0;
  271.     pFont->info.firstCol = 256;
  272.     pFont->info.lastCol = 0;
  273.     nignored = 0;
  274.     for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) {
  275.     int         t;
  276.     int         wx;        /* x component of width */
  277.     int         wy;        /* y component of width */
  278.     int         bw;        /* bounding-box width */
  279.     int         bh;        /* bounding-box height */
  280.     int         bl;        /* bounding-box left */
  281.     int         bb;        /* bounding-box bottom */
  282.     int         enc,
  283.                 enc2;    /* encoding */
  284.     unsigned char *p;    /* temp pointer into line */
  285.     char        charName[100];
  286.     int         ignore;
  287.  
  288.     if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) {
  289.         bdfError("bad character name in BDF file\n");
  290.         goto BAILOUT;    /* bottom of function, free and return error */
  291.     }
  292.     if (bitmapExtra)
  293.         bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL);
  294.  
  295.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  296.     if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) {
  297.         bdfError("bad 'ENCODING' in BDF file\n");
  298.         goto BAILOUT;
  299.     }
  300.     if (enc < -1 || t == 2 && enc2 < -1) {
  301.         bdfError("bad ENCODING value");
  302.         goto BAILOUT;
  303.     }
  304.     if (t == 2 && enc == -1)
  305.         enc = enc2;
  306.     ignore = 0;
  307.     if (enc == -1) {
  308.         if (!bitmapExtra) {
  309.         nignored++;
  310.         ignore = 1;
  311.         }
  312.     } else if (enc > MAXENCODING) {
  313.         bdfError("char '%s' has encoding too large (%d)\n",
  314.              charName, enc);
  315.     } else {
  316.         char_row = (enc >> 8) & 0xFF;
  317.         char_col = enc & 0xFF;
  318.         if (char_row < pFont->info.firstRow)
  319.         pFont->info.firstRow = char_row;
  320.         if (char_row > pFont->info.lastRow)
  321.         pFont->info.lastRow = char_row;
  322.         if (char_col < pFont->info.firstCol)
  323.         pFont->info.firstCol = char_col;
  324.         if (char_col > pFont->info.lastCol)
  325.         pFont->info.lastCol = char_col;
  326.         if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
  327.         bdfEncoding[char_row] =
  328.             (CharInfoPtr *) xalloc(256 * sizeof(CharInfoPtr));
  329.         if (!bdfEncoding[char_row]) {
  330.             bdfError("Couldn't allocate row %d of encoding (%d*%d)\n",
  331.                  char_row, INDICES, sizeof(CharInfoPtr));
  332.             goto BAILOUT;
  333.         }
  334.         for (i = 0; i < 256; i++)
  335.             bdfEncoding[char_row][i] = (CharInfoPtr) NULL;
  336.         }
  337.         if (bdfEncoding[char_row] != NULL) {
  338.         bdfEncoding[char_row][char_col] = ci;
  339.         numEncodedGlyphs++;
  340.         }
  341.     }
  342.  
  343.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  344.     if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) {
  345.         bdfError("bad 'SWIDTH'\n");
  346.         goto BAILOUT;
  347.     }
  348.     if (wy != 0) {
  349.         bdfError("SWIDTH y value must be zero\n");
  350.         goto BAILOUT;
  351.     }
  352.     if (bitmapExtra)
  353.         bitmapExtra->sWidths[ndx] = wx;
  354.  
  355. /* 5/31/89 (ef) -- we should be able to ditch the character and recover */
  356. /*        from all of these.                    */
  357.  
  358.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  359.     if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) {
  360.         bdfError("bad 'DWIDTH'\n");
  361.         goto BAILOUT;
  362.     }
  363.     if (wy != 0) {
  364.         bdfError("DWIDTH y value must be zero\n");
  365.         goto BAILOUT;
  366.     }
  367.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  368.     if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) {
  369.         bdfError("bad 'BBX'\n");
  370.         goto BAILOUT;
  371.     }
  372.     if ((bh < 0) || (bw < 0)) {
  373.         bdfError("character '%s' has a negative sized bitmap, %dx%d\n",
  374.              charName, bw, bh);
  375.         goto BAILOUT;
  376.     }
  377.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  378.     if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) {
  379.         for (p = line + strlen("ATTRIBUTES ");
  380.             (*p == ' ') || (*p == '\t');
  381.             p++)
  382.          /* empty for loop */ ;
  383.         ci->metrics.attributes = bdfHexByte(p) << 8 + bdfHexByte(p + 2);
  384.         line = bdfGetLine(file, lineBuf, BDFLINELEN);
  385.     } else
  386.         ci->metrics.attributes = 0;
  387.  
  388.     if (!line || !bdfIsPrefix(line, "BITMAP")) {
  389.         bdfError("missing 'BITMAP'\n");
  390.         goto BAILOUT;
  391.     }
  392.     /* collect data for generated properties */
  393.     if ((strlen(charName) == 1)) {
  394.         if ((charName[0] >= '0') && (charName[0] <= '9')) {
  395.         pState->digitWidths += wx;
  396.         pState->digitCount++;
  397.         } else if (charName[0] == 'x') {
  398.         pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb;
  399.         }
  400.     }
  401.     if (!ignore) {
  402.         ci->metrics.leftSideBearing = bl;
  403.         ci->metrics.rightSideBearing = bl + bw;
  404.         ci->metrics.ascent = bh + bb;
  405.         ci->metrics.descent = -bb;
  406.         ci->metrics.characterWidth = wx;
  407.         ci->bits = NULL;
  408.         bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes);
  409.         ci++;
  410.         ndx++;
  411.     } else
  412.         bdfSkipBitmap(file, bh);
  413.  
  414.     line = bdfGetLine(file, lineBuf, BDFLINELEN);    /* get STARTCHAR or
  415.                              * ENDFONT */
  416.     }
  417.  
  418.     if (ndx + nignored != nchars) {
  419.     bdfError("%d too few characters\n", nchars - (ndx + nignored));
  420.     goto BAILOUT;
  421.     }
  422.     nchars = ndx;
  423.     bitmapFont->num_chars = nchars;
  424.     if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) {
  425.     bdfError("more characters than specified\n");
  426.     goto BAILOUT;
  427.     }
  428.     if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) {
  429.     bdfError("missing 'ENDFONT'\n");
  430.     goto BAILOUT;
  431.     }
  432.     if (numEncodedGlyphs == 0)
  433.     bdfWarning("No characters with valid encodings\n");
  434.  
  435.     nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) *
  436.     (pFont->info.lastCol - pFont->info.firstCol + 1);
  437.     bitmapFont->encoding = (CharInfoPtr *) xalloc(nencoding * sizeof(CharInfoPtr));
  438.     if (!bitmapFont->encoding) {
  439.     bdfError("Couldn't allocate ppCI (%d,%d)\n",
  440.          nencoding,
  441.          sizeof(CharInfoPtr));
  442.     goto BAILOUT;
  443.     }
  444.     pFont->info.allExist = TRUE;
  445.     i = 0;
  446.     for (char_row = pFont->info.firstRow;
  447.         char_row <= pFont->info.lastRow;
  448.         char_row++) {
  449.     if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
  450.         pFont->info.allExist = FALSE;
  451.         for (char_col = pFont->info.firstCol;
  452.             char_col <= pFont->info.lastCol;
  453.             char_col++) {
  454.         bitmapFont->encoding[i++] = NullCharInfo;
  455.         }
  456.     } else {
  457.         for (char_col = pFont->info.firstCol;
  458.             char_col <= pFont->info.lastCol;
  459.             char_col++) {
  460.         if (!bdfEncoding[char_row][char_col])
  461.             pFont->info.allExist = FALSE;
  462.         bitmapFont->encoding[i++] = bdfEncoding[char_row][char_col];
  463.         }
  464.     }
  465.     }
  466.     for (i = 0; i < 256; i++)
  467.     if (bdfEncoding[i])
  468.         xfree(bdfEncoding[i]);
  469.     return (TRUE);
  470. BAILOUT:
  471.     for (i = 0; i < 256; i++)
  472.     if (bdfEncoding[i])
  473.         xfree(bdfEncoding[i]);
  474.     /* bdfFreeFontBits will clean up the rest */
  475.     return (FALSE);
  476. }
  477.  
  478. /***====================================================================***/
  479.  
  480. Bool
  481. bdfReadHeader(file, pState)
  482.     FontFilePtr file;
  483.     bdfFileState *pState;
  484. {
  485.     unsigned char *line;
  486.     char        namebuf[BDFLINELEN];
  487.     int         tmp;
  488.     char        lineBuf[BDFLINELEN];
  489.  
  490.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  491.     if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 ||
  492.         !bdfStrEqual(namebuf, "2.1")) {
  493.     bdfError("bad 'STARTFONT'\n");
  494.     return (FALSE);
  495.     }
  496.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  497.     if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) {
  498.     bdfError("bad 'FONT'\n");
  499.     return (FALSE);
  500.     }
  501.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  502.     if (!line || !bdfIsPrefix(line, "SIZE")) {
  503.     bdfError("missing 'SIZE'\n");
  504.     return (FALSE);
  505.     }
  506.     if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize,
  507.            &pState->resolution_x, &pState->resolution_y) != 3) {
  508.     bdfError("bad 'SIZE'\n");
  509.     return (FALSE);
  510.     }
  511.     if (pState->pointSize < 1 ||
  512.     pState->resolution_x < 1 || pState->resolution_y < 1) {
  513.     bdfError("SIZE values must be > 0\n");
  514.     return (FALSE);
  515.     }
  516.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  517.     if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) {
  518.     bdfError("missing 'FONTBOUNDINGBOX'\n");
  519.     return (FALSE);
  520.     }
  521.     return (TRUE);
  522. }
  523.  
  524. /***====================================================================***/
  525.  
  526. static Bool
  527. bdfReadProperties(file, pFont, pState)
  528.     FontFilePtr file;
  529.     FontPtr     pFont;
  530.     bdfFileState *pState;
  531. {
  532.     int         nProps,
  533.                 nextProp;
  534.     char       *stringProps;
  535.     FontPropPtr props;
  536.     char        namebuf[BDFLINELEN],
  537.                 secondbuf[BDFLINELEN],
  538.                 thirdbuf[BDFLINELEN];
  539.     unsigned char *line;
  540.     char        lineBuf[BDFLINELEN];
  541.     BitmapFontPtr  bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
  542.  
  543.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  544.     if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) {
  545.     bdfError(file, "missing 'STARTPROPERTIES'\n");
  546.     return (FALSE);
  547.     }
  548.     if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) {
  549.     bdfError("bad 'STARTPROPERTIES'\n");
  550.     return (FALSE);
  551.     }
  552.     pFont->info.isStringProp = NULL;
  553.     pFont->info.props = NULL;
  554.  
  555.     stringProps = (char *) xalloc((nProps + BDF_GENPROPS) * sizeof(char));
  556.     pFont->info.isStringProp = stringProps;
  557.     if (stringProps == NULL) {
  558.     bdfError("Couldn't allocate stringProps (%d*%d)\n",
  559.          (nProps + BDF_GENPROPS), sizeof(Bool));
  560.     goto BAILOUT;
  561.     }
  562.     pFont->info.props = props = (FontPropPtr) xalloc((nProps + BDF_GENPROPS) *
  563.                              sizeof(FontPropRec));
  564.     if (props == NULL) {
  565.     bdfError("Couldn't allocate props (%d*%d)\n", (nProps + BDF_GENPROPS,
  566.                                sizeof(FontPropRec)));
  567.     goto BAILOUT;
  568.     }
  569.     nextProp = 0;
  570.     while (nProps-- > 0) {
  571.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  572.     if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) {
  573.         bdfError("%d too few properites\n", nProps + 1);
  574.         goto BAILOUT;
  575.     }
  576.     while (*line && isspace(*line))
  577.         line++;
  578.  
  579.     switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) {
  580.     default:
  581.         bdfError("missing '%s' parameter value\n", namebuf);
  582.         goto BAILOUT;
  583.         break;
  584.  
  585.     case 2:
  586.         /*
  587.          * Possibilites include: valid quoted string with no white space
  588.          * valid integer value invalid value
  589.          */
  590.         if (secondbuf[0] == '"') {
  591.         stringProps[nextProp] = TRUE;
  592.         props[nextProp].value =
  593.             bdfGetPropertyValue(line + strlen(namebuf) + 1);
  594.         if (!props[nextProp].value)
  595.             goto BAILOUT;
  596.         break;
  597.         } else if (bdfIsInteger(secondbuf)) {
  598.         stringProps[nextProp] = FALSE;
  599.         props[nextProp].value = atoi(secondbuf);
  600.         break;
  601.         } else {
  602.         bdfError("invalid '%s' parameter value\n", namebuf);
  603.         goto BAILOUT;
  604.         }
  605.  
  606.     case 3:
  607.         /*
  608.          * Possibilites include: valid quoted string with some white space
  609.          * invalid value (reject even if second string is integer)
  610.          */
  611.         if (secondbuf[0] == '"') {
  612.         stringProps[nextProp] = TRUE;
  613.         props[nextProp].value =
  614.             bdfGetPropertyValue(line + strlen(namebuf) + 1);
  615.         if (!props[nextProp].value)
  616.             goto BAILOUT;
  617.         break;
  618.         } else {
  619.         bdfError("invalid '%s' parameter value\n", namebuf);
  620.         goto BAILOUT;
  621.         }
  622.     }
  623.     props[nextProp].name = bdfForceMakeAtom(namebuf, NULL);
  624.     if (props[nextProp].name == None) {
  625.         bdfError("Empty property name.\n");
  626.         goto BAILOUT;
  627.     }
  628.     if (!bdfSpecialProperty(pFont, &props[nextProp],
  629.                 stringProps[nextProp], pState))
  630.         nextProp++;
  631.     }
  632.  
  633.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  634.     if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) {
  635.     bdfError("missing 'ENDPROPERTIES'\n");
  636.     goto BAILOUT;
  637.     }
  638.     if (!pState->haveFontAscent || !pState->haveFontDescent) {
  639.     bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n");
  640.     goto BAILOUT;
  641.     }
  642.     if (bitmapFont->bitmapExtra) {
  643.     bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent;
  644.     bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent;
  645.     }
  646.     if (!pState->pointSizeProp) {
  647.     props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL);
  648.     props[nextProp].value = (INT32) (pState->pointSize * 10.0);
  649.     stringProps[nextProp] = FALSE;
  650.     pState->pointSizeProp = &props[nextProp];
  651.     nextProp++;
  652.     }
  653.     if (!pState->fontProp) {
  654.     props[nextProp].name = bdfForceMakeAtom("FONT", NULL);
  655.     props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL);
  656.     stringProps[nextProp] = TRUE;
  657.     pState->fontProp = &props[nextProp];
  658.     nextProp++;
  659.     }
  660.     if (!pState->weightProp) {
  661.     props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL);
  662.     props[nextProp].value = -1;    /* computed later */
  663.     stringProps[nextProp] = FALSE;
  664.     pState->weightProp = &props[nextProp];
  665.     nextProp++;
  666.     }
  667.     if (!pState->resolutionProp &&
  668.     pState->resolution_x == pState->resolution_y) {
  669.     props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL);
  670.     props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27);
  671.     stringProps[nextProp] = FALSE;
  672.     pState->resolutionProp = &props[nextProp];
  673.     nextProp++;
  674.     }
  675.     if (!pState->resolutionXProp) {
  676.     props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL);
  677.     props[nextProp].value = (INT32) pState->resolution_x;
  678.     stringProps[nextProp] = FALSE;
  679.     pState->resolutionProp = &props[nextProp];
  680.     nextProp++;
  681.     }
  682.     if (!pState->resolutionYProp) {
  683.     props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL);
  684.     props[nextProp].value = (INT32) pState->resolution_y;
  685.     stringProps[nextProp] = FALSE;
  686.     pState->resolutionProp = &props[nextProp];
  687.     nextProp++;
  688.     }
  689.     if (!pState->xHeightProp) {
  690.     props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL);
  691.     props[nextProp].value = -1;    /* computed later */
  692.     stringProps[nextProp] = FALSE;
  693.     pState->xHeightProp = &props[nextProp];
  694.     nextProp++;
  695.     }
  696.     if (!pState->quadWidthProp) {
  697.     props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL);
  698.     props[nextProp].value = -1;    /* computed later */
  699.     stringProps[nextProp] = FALSE;
  700.     pState->quadWidthProp = &props[nextProp];
  701.     nextProp++;
  702.     }
  703.     pFont->info.nprops = nextProp;
  704.     return (TRUE);
  705. BAILOUT:
  706.     if (pFont->info.isStringProp) {
  707.     xfree(pFont->info.isStringProp);
  708.     pFont->info.isStringProp = NULL;
  709.     }
  710.     if (pFont->info.props) {
  711.     xfree(pFont->info.props);
  712.     pFont->info.props = NULL;
  713.     }
  714.     while (line && bdfIsPrefix(line, "ENDPROPERTIES"))
  715.     line = bdfGetLine(file, lineBuf, BDFLINELEN);
  716.     return (FALSE);
  717. }
  718.  
  719. /***====================================================================***/
  720.  
  721. int
  722. bdfReadFont(pFont, file, bit, byte, glyph, scan)
  723.     FontPtr     pFont;
  724.     FontFilePtr file;
  725.     int         bit,
  726.                 byte,
  727.                 glyph,
  728.                 scan;
  729. {
  730.     bdfFileState state;
  731.     xCharInfo  *min,
  732.                *max;
  733.     BitmapFontPtr  bitmapFont;
  734.  
  735.     pFont->fontPrivate = 0;
  736.  
  737.     bzero(&state, sizeof(bdfFileState));
  738.  
  739.     if (!bdfReadHeader(file, &state))
  740.     goto BAILOUT;
  741.  
  742.     bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec));
  743.     if (!bitmapFont)
  744.     goto BAILOUT;
  745.  
  746.     pFont->fontPrivate = (pointer) bitmapFont;
  747.     bitmapFont->metrics = 0;
  748.     bitmapFont->ink_metrics = 0;
  749.     bitmapFont->bitmaps = 0;
  750.     bitmapFont->encoding = 0;
  751.     bitmapFont->pDefault = NULL;
  752.     bitmapFont->bitmapExtra = (BitmapExtraPtr) xalloc(sizeof(BitmapExtraRec));
  753.     bitmapFont->bitmapExtra->glyphNames = 0;
  754.     bitmapFont->bitmapExtra->sWidths = 0;
  755.  
  756.     if (!bdfReadProperties(file, pFont, &state))
  757.     goto BAILOUT;
  758.  
  759.     if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan))
  760.     goto BAILOUT;
  761.  
  762.     if (state.haveDefaultCh) {
  763.     unsigned int r, c, cols;
  764.  
  765.     r = pFont->info.defaultCh >> 8;
  766.     c = pFont->info.defaultCh & 0xFF;
  767.     if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
  768.         pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
  769.         cols = pFont->info.lastCol - pFont->info.firstCol + 1;
  770.         r = r - pFont->info.firstRow;
  771.         c = c - pFont->info.firstCol;
  772.         bitmapFont->pDefault = bitmapFont->encoding[r * cols + c];
  773.     }
  774.     }
  775.     pFont->bit = bit;
  776.     pFont->byte = byte;
  777.     pFont->glyph = glyph;
  778.     pFont->scan = scan;
  779.     pFont->info.anamorphic = FALSE;
  780.     bitmapComputeFontBounds(pFont);
  781.     if (FontCouldBeTerminal(&pFont->info)) {
  782.     bdfPadToTerminal(pFont);
  783.     bitmapComputeFontBounds(pFont);
  784.     }
  785.     FontComputeInfoAccelerators(&pFont->info);
  786.     if (bitmapFont->bitmapExtra)
  787.     FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info);
  788.     if (pFont->info.constantMetrics)
  789.     bitmapAddInkMetrics(pFont);
  790.     if (bitmapFont->bitmapExtra)
  791.     bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics;
  792.  
  793.     bitmapComputeFontInkBounds(pFont);
  794. /*    ComputeFontAccelerators (pFont); */
  795.  
  796.     /* generate properties */
  797.     min = &pFont->info.ink_minbounds;
  798.     max = &pFont->info.ink_maxbounds;
  799.     if (state.xHeightProp && (state.xHeightProp->value == -1))
  800.     state.xHeightProp->value = state.exHeight ?
  801.         state.exHeight : min->ascent;
  802.  
  803.     if (state.quadWidthProp && (state.quadWidthProp->value == -1))
  804.     state.quadWidthProp->value = state.digitCount ?
  805.         (INT32) ((float) state.digitWidths / (float) state.digitCount) :
  806.         (min->characterWidth + max->characterWidth) / 2;
  807.  
  808.     if (state.weightProp && (state.weightProp->value == -1))
  809.     state.weightProp->value = bitmapComputeWeight(pFont);
  810.  
  811.     pFont->get_glyphs = bitmapGetGlyphs;
  812.     pFont->get_metrics = bitmapGetMetrics;
  813.     pFont->unload_font = bdfUnloadFont;
  814.     return Successful;
  815. BAILOUT:
  816.     if (pFont->fontPrivate)
  817.     bdfFreeFontBits (pFont);
  818.     return AllocError;
  819. }
  820.  
  821. bdfFreeFontBits(pFont)
  822.     FontPtr pFont;
  823. {
  824.     BitmapFontPtr  bitmapFont;
  825.     BitmapExtraPtr bitmapExtra;
  826.     int         i;
  827.  
  828.     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
  829.     bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
  830.     xfree(bitmapFont->ink_metrics);
  831.     xfree(bitmapFont->encoding);
  832.     for (i = 0; i < bitmapFont->num_chars; i++)
  833.     xfree(bitmapFont->metrics[i].bits);
  834.     xfree(bitmapFont->metrics);
  835.     if (bitmapExtra)
  836.     {
  837.     xfree (bitmapExtra->glyphNames);
  838.     xfree (bitmapExtra->sWidths);
  839.     xfree (bitmapExtra);
  840.     }
  841.     xfree(pFont->info.props);
  842.     xfree(bitmapFont);
  843. }
  844.  
  845. int
  846. bdfReadFontInfo(pFontInfo, file)
  847.     FontInfoPtr pFontInfo;
  848.     FontFilePtr file;
  849. {
  850.     FontRec     font;
  851.     int         ret;
  852.  
  853.     ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1);
  854.     if (ret == Successful) {
  855.     *pFontInfo = font.info;
  856.     font.info.props = 0;
  857.     font.info.isStringProp = 0;
  858.     font.info.nprops = 0;
  859.     bdfFreeFontBits (&font);
  860.     }
  861.     return ret;
  862. }
  863.  
  864. void
  865. bdfUnloadFont(pFont)
  866.     FontPtr     pFont;
  867. {
  868.     bdfFreeFontBits (pFont);
  869.     xfree(pFont);
  870. }
  871.  
  872. static Bool
  873. bdfPadToTerminal(pFont)
  874.     FontPtr     pFont;
  875. {
  876.     BitmapFontPtr  bitmapFont;
  877.     BitmapExtraPtr bitmapExtra;
  878.     int         i;
  879.     int         new_size;
  880.     CharInfoRec new;
  881.     int         w,
  882.                 h;
  883.  
  884.     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
  885.     new.metrics.ascent = pFont->info.fontAscent;
  886.     new.metrics.descent = pFont->info.fontDescent;
  887.     new.metrics.leftSideBearing = 0;
  888.     new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth;
  889.     new.metrics.characterWidth = new.metrics.rightSideBearing;
  890.     new_size = BYTES_FOR_GLYPH(&new, pFont->glyph);
  891.     for (i = 0; i < bitmapFont->num_chars; i++) {
  892.     new.bits = (char *) xalloc(new_size);
  893.     if (!new.bits)
  894.         return FALSE;
  895.     FontCharReshape(pFont, &bitmapFont->metrics[i], &new);
  896.     xfree(bitmapFont->metrics[i].bits);
  897.     bitmapFont->metrics[i] = new;
  898.     }
  899.     bitmapExtra = bitmapFont->bitmapExtra;
  900.     if (bitmapExtra) {
  901.     w = GLYPHWIDTHPIXELS(&new);
  902.     h = GLYPHHEIGHTPIXELS(&new);
  903.     for (i = 0; i < GLYPHPADOPTIONS; i++)
  904.         bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars *
  905.         (BYTES_PER_ROW(w, 1 << i) * h);
  906.     }
  907.     return TRUE;
  908. }
  909.