home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / fonts / server / MacFS / MacFont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-29  |  18.2 KB  |  621 lines

  1. /***********************************************************************
  2. Copyright 1991 by Apple Computer, Inc, Cupertino, California
  3.             All Rights Reserved
  4.  
  5. Permission to use, copy, modify, and distribute this software
  6. for any purpose and without fee is hereby granted, provided
  7. that the above copyright notice appear in all copies.
  8.  
  9. APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS,
  10. OR IMPLIED, WITH RESPECT TO THIS SOFTWARE, ITS QUALITY,
  11. PERFORMANCE, MERCHANABILITY, OR FITNESS FOR A PARTICULAR
  12. PURPOSE. AS A RESULT, THIS SOFTWARE IS PROVIDED "AS IS,"
  13. AND YOU THE USER ARE ASSUMING THE ENTIRE RISK AS TO ITS
  14. QUALITY AND PERFORMANCE. IN NO EVENT WILL APPLE BE LIABLE 
  15. FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  16. DAMAGES RESULTING FROM ANY DEFECT IN THE SOFTWARE.
  17.  
  18. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE
  19. AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR
  20. IMPLIED.
  21.  
  22. ***********************************************************************/
  23. #include "MacFont.h"
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include "fontfilest.h"
  28. #include "bitmap.h"
  29. #include "font.h"
  30.  
  31. #include "MacISO.h"
  32. #define TOISO(C)    (MacToLatin1[C])    /* Convert a character to ISO Latin1 mapping */
  33. #define TOMAC(C)    (Latin1ToMac[C])    /* Convert a character to Mac ASCII mapping */
  34.  
  35. static void
  36. FastCharInkMetrics32(pFont, pCI, pInk)
  37.     FontPtr     pFont;
  38.     CharInfoPtr pCI;
  39.     xCharInfo  *pInk;
  40. {
  41.     int ascent, descent;
  42.     unsigned int savebits;
  43.     register int vpos, inkAscent, inkDescent, lb, rb;
  44.     register unsigned int *p;
  45.     register unsigned int charbits;
  46.  
  47.     pInk->characterWidth = pCI->metrics.characterWidth;
  48.     pInk->attributes = pCI->metrics.attributes;
  49.  
  50.     ascent = pCI->metrics.ascent;
  51.     descent = pCI->metrics.descent;
  52.  
  53.     p = (unsigned int *) pCI->bits;
  54.     charbits = 0;
  55.     inkAscent = ascent + 1;
  56.  
  57.     for (vpos = ascent; --vpos >= -descent; p++) {
  58.         if (*p != 0) {
  59.             if (inkAscent > ascent) /* must be first inked row */
  60.                 inkAscent = vpos + 1;
  61.             inkDescent = -vpos; /* descends at least this far */
  62.             charbits |= *p;
  63.         }
  64.     }
  65.  
  66.     if (inkAscent > ascent) {
  67.         /*
  68.          * special case -- font with no bits gets all zeros
  69.          */
  70.         pInk->leftSideBearing = pCI->metrics.leftSideBearing;
  71.         pInk->rightSideBearing = pCI->metrics.leftSideBearing;
  72.         pInk->ascent = 0;
  73.         pInk->descent = 0;
  74.         return;
  75.     } else {
  76.         pInk->ascent = inkAscent;
  77.         pInk->descent = inkDescent;
  78.     }
  79.  
  80.     savebits = charbits;
  81.     lb = pCI->metrics.leftSideBearing;
  82.     while ((charbits & 0x80000000) == 0) {
  83.         charbits <<= 1;
  84.         lb++;
  85.     }
  86.     pInk->leftSideBearing = lb;
  87.  
  88.     charbits = savebits;
  89.     rb = pCI->metrics.rightSideBearing;
  90.     while ((charbits & 0x00000001) == 0) {
  91.         charbits >>= 1;
  92.         rb--;
  93.     }
  94.     pInk->rightSideBearing = rb;
  95. }
  96.  
  97. static void
  98. FastCharInkMetrics64(pFont, pCI, pInk)
  99.     FontPtr     pFont;
  100.     CharInfoPtr pCI;
  101.     xCharInfo  *pInk;
  102. {
  103.     int ascent, descent;
  104.     unsigned int savebits1, savebits2;
  105.     register int vpos, inkAscent, inkDescent, lb, rb;
  106.     register unsigned int *p0, *p1;
  107.     register unsigned int charbits1, charbits2;
  108.  
  109.     pInk->characterWidth = pCI->metrics.characterWidth;
  110.     pInk->attributes = pCI->metrics.attributes;
  111.  
  112.     ascent = pCI->metrics.ascent;
  113.     descent = pCI->metrics.descent;
  114.  
  115.     p0 = (unsigned int *) pCI->bits;
  116.     p1 = p0 + 1;
  117.     charbits1 = 0;
  118.     charbits2 = 0;
  119.     inkAscent = ascent + 1;
  120.  
  121.     for (vpos = ascent; --vpos >= -descent; p0 += 2, p1 += 2) {
  122.         if (*p0 != 0 || *p1 != 0) {
  123.             if (inkAscent > ascent) /* must be first inked row */
  124.                 inkAscent = vpos + 1;
  125.             inkDescent = -vpos; /* descends at least this far */
  126.             charbits1 |= *p0;
  127.             charbits2 |= *p1;
  128.         }
  129.     }
  130.  
  131.     if (inkAscent > ascent) {
  132.         /*
  133.          * special case -- font with no bits gets all zeros
  134.          */
  135.         pInk->leftSideBearing = pCI->metrics.leftSideBearing;
  136.         pInk->rightSideBearing = pCI->metrics.leftSideBearing;
  137.         pInk->ascent = 0;
  138.         pInk->descent = 0;
  139.         return;
  140.     } else {
  141.         pInk->ascent = inkAscent;
  142.         pInk->descent = inkDescent;
  143.     }
  144.  
  145.     savebits1 = charbits1;
  146.     savebits2 = charbits2;
  147.     lb = pCI->metrics.leftSideBearing;
  148.     if (charbits1)
  149.         while ((charbits1 & 0x80000000) == 0) {
  150.             charbits1 <<= 1;
  151.             lb++;
  152.         }
  153.     else {
  154.         lb += 32;
  155.         while ((charbits2 & 0x80000000) == 0) {
  156.             charbits2 <<= 1;
  157.             lb++;
  158.         }
  159.     }
  160.     pInk->leftSideBearing = lb;
  161.  
  162.     charbits1 = savebits1;
  163.     charbits2 = savebits2;
  164.     rb = pCI->metrics.rightSideBearing;
  165.     if(charbits2)
  166.         while ((charbits2 & 0x00000001) == 0) {
  167.             charbits2 >>= 1;
  168.             rb--;
  169.         }
  170.     else {
  171.         rb -= 32;
  172.         while ((charbits1 & 0x00000001) == 0) {
  173.             charbits1 >>= 1;
  174.             rb--;
  175.         }
  176.     }
  177.     pInk->rightSideBearing = rb;
  178. }
  179.  
  180. static unsigned char macFirst, macLast;
  181.  
  182. static int widthOf (ch)
  183.     int ch;
  184. {
  185.     if (ch < macFirst || ch > macLast) {
  186.         return (0);
  187.     } else {
  188.         return (CharWidth (ch));
  189.     }
  190. }
  191.  
  192.  
  193. static Point square = {1, 1};
  194.  
  195. int OpenMacFont (pFont, pMacPriv, name, pixel, res_x, res_y)
  196.     FontPtr     pFont;
  197.     MacBitmapFontRecPtr pMacPriv;
  198.     char *name;
  199. {
  200.     char fname [MAXFONTNAMELEN];
  201.     char *ptr, *ptr1, *ptr2, *ptr3, *ptr4, *ptr5, *ptr6, 
  202.      *ptr7, *ptr8, *ptr9, *ptr10, *ptr11, *ptr12, *ptr13;
  203.     char *family_name, *weight_name, *slant, *setwidth_name, *add_style_name, 
  204.      *spacing, *registry, *encoding;
  205.     GrafPtr pgp, savePort;
  206.     FMetricRec *pfm;
  207.     short fNum = 0;
  208.     short face = normal;
  209.  
  210.     pMacPriv->pgp = 0;
  211.     pMacPriv->pfm = 0;
  212.     pMacPriv->forceMono = false;
  213.     pMacPriv->privateEncoding = false;
  214.  
  215.     strcpy (fname, name);
  216.  
  217.     /* The ptr? below are set at the '-' just preceding the field named in the
  218.        comment */
  219.  
  220.     if (!(*fname == '-') ||                /* foundry */
  221.         !(ptr1 = ptr = index(fname + 1, '-')) ||    /* family_name */
  222.         !(ptr2 = ptr = index(ptr + 1, '-')) ||    /* weight_name */
  223.         !(ptr3 = ptr = index(ptr + 1, '-')) ||    /* slant */
  224.         !(ptr4 = ptr = index(ptr + 1, '-')) ||    /* setwidth_name */
  225.         !(ptr5 = ptr = index(ptr + 1, '-')) ||    /* add_style_name */
  226.         !(ptr6 = ptr = index(ptr + 1, '-')) ||    /* pixel_size */
  227.         !(ptr7 = ptr = index(ptr + 1, '-')) ||    /* point_size */
  228.         !(ptr8 = ptr = index(ptr + 1, '-')) ||    /* resolution_x */
  229.         !(ptr9 = ptr = index(ptr + 1, '-')) ||    /* resolution_y */
  230.         !(ptr10 = ptr = index(ptr + 1, '-')) ||    /* spacing */
  231.         !(ptr11 = ptr = index(ptr + 1, '-')) ||    /* average_width */
  232.         !(ptr12 = ptr = index(ptr + 1, '-')) ||    /* charset_registry */
  233.         !(ptr13 = ptr = index(ptr + 1, '-')) ||    /* charset_encoding */
  234.         index(ptr + 1, '-'))            /* Too many '-'s ! */
  235.     return BadFontName;
  236.     
  237.     family_name = ptr1 + 1;
  238.     *ptr2 = '\0';
  239.  
  240.     weight_name = ptr2 + 1;
  241.     *ptr3 = '\0';
  242.  
  243.     slant = ptr3 + 1;
  244.     *ptr4 = '\0';
  245.  
  246.     setwidth_name = ptr4 + 1;
  247.     *ptr5 = '\0';
  248.  
  249.     add_style_name = ptr5 + 1;
  250.     *ptr6 = '\0';
  251.  
  252.     spacing = ptr10 + 1;
  253.     *ptr11 = '\0';
  254.  
  255.     registry = ptr12 + 1;
  256.     *ptr13 = '\0';
  257.  
  258.     encoding = ptr13 + 1; /* zero terminated at the end of name */
  259.     
  260.  
  261.     if (!strcmp(weight_name, "bold"))
  262.         face |= bold;
  263.  
  264.     if (!strcmp(slant, "i"))
  265.         face |= italic;
  266.  
  267.     if (!strcmp(setwidth_name, "condensed"))
  268.         face |= condense;
  269.  
  270.     if (!strcmp(setwidth_name, "extended"))
  271.         face |= extend;
  272.  
  273.     if (!strcmp(add_style_name, "underline"))
  274.         face |= underline;
  275.  
  276.     if (!strcmp(add_style_name, "outline"))
  277.         face |= outline;
  278.  
  279.     if (!strcmp(add_style_name, "shadow"))
  280.         face |= shadow;
  281.  
  282.     if (!strcmp(spacing, "m"))
  283.         pMacPriv->forceMono = true; /* XXX Do we really want to offer this? */
  284.  
  285.     if (!strcmp(registry, "apple") && !strcmp(encoding, "fontspecific"))
  286.         pMacPriv->privateEncoding = true;
  287.  
  288.     pgp = (GrafPtr) NewPtr(sizeof(GrafPort));
  289.     if (!pgp) {
  290.         return (AllocError);
  291.     }
  292.  
  293.     pfm = (FMetricRec *) NewPtr(sizeof(FMetricRec));
  294.     if (!pfm) {
  295.         DisposPtr (pgp);
  296.         return (AllocError);
  297.     }
  298.  
  299.     GetPort (&savePort);
  300.     OpenPort (pgp);
  301.  
  302.     getfnum (family_name, &fNum);
  303.  
  304.     if (!fNum) {
  305.         char sysName [256];
  306.         /* Per technote about font names */
  307.         getfontname (systemFont, sysName);
  308.         if (relstring (sysName, family_name, false, true)) 
  309.         {
  310.             DisposPtr (pfm);
  311.             ClosePort (pgp);
  312.             DisposPtr (pgp);
  313.             SetPort (savePort);
  314.             return (BadFontName);
  315.         }
  316.     }
  317.  
  318.     TextFont (fNum);
  319.     TextSize (pixel);
  320.     TextFace (face);
  321.     FontMetrics (pfm);
  322.  
  323.     /* IM Volume 6 12-15 says: Be careful with outline fonts. The font's designer
  324.        may decide that there is a lower limit to the point size at which the
  325.        font looks acceptable.  */
  326.     if (CIsOutline(square, square) && !RealFont(fNum, pixel))
  327.     {
  328.         DisposPtr (pfm);
  329.         ClosePort (pgp);
  330.         DisposPtr (pgp);
  331.         SetPort (savePort);
  332.         return (BadFontName);
  333.     }
  334.  
  335.     pMacPriv->pgp = pgp;
  336.     pMacPriv->pfm = pfm;
  337.     SetPort (savePort);
  338.  
  339.     return (Successful);                /* Eureka! */
  340. }
  341.  
  342. int ConvertMacFont (pFont, pMacPriv, bit, byte, glyph, scan)
  343.     FontPtr     pFont;
  344.     MacBitmapFontRecPtr pMacPriv;
  345.     int         bit, byte, glyph, scan;
  346. {
  347.     BitmapFontPtr  bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
  348.     register FontInfoPtr fi;            /* Font description */
  349.     register CharInfoPtr cip;            /* Character being worked on */
  350.     register CharInfoPtr *enc;
  351.     register unsigned ch;
  352.     int nchars, height;
  353.     unsigned isoFirst, isoLast;
  354.     int digitCount, digitWidths;
  355.     Handle frH;                /* FontRec handle -- n.b.: might be sfnt rec handle */
  356.     Point numer, denom;
  357.     GrafPtr savePort;
  358.     WidthTable *wtP;
  359.     int maxWidth;
  360.     short yMin, yMax;
  361.     BitMap bm, gbm;            /* bm is bitmap for gp, gbm is bitmap for pGlyphs */
  362.     CharInfoRec bmcip;
  363.     xCharInfo bmink;
  364.     Rect srcR, dstR;
  365.     int bmorg, Mwidth;
  366.     int gbmSize;
  367.     OSErr ret;
  368.  
  369.     pMacPriv->avgWidth = 0; /* DECIpoints */
  370.     pMacPriv->xHeight = 0;
  371.     pMacPriv->quadWidth = 0;
  372.     pMacPriv->weight = 0;
  373.     
  374.     GetPort (&savePort);
  375.     SetPort (pMacPriv->pgp);
  376.  
  377.     SetCursor (*GetCursor (watchCursor));
  378.     wtP = *(WidthTable **) pMacPriv->pfm->wTabHandle;
  379.     frH = wtP -> tabFont;
  380.     numer = wtP -> inNumer;
  381.     denom = wtP -> inDenom;
  382.     maxWidth = FixRound (pMacPriv->pfm->widMax) * 2;    /* Glyphs can be no wider than this */
  383.     if (maxWidth < 32)
  384.         maxWidth = 32;
  385.     else if (maxWidth < 64)
  386.         maxWidth = 64;
  387.     bmorg = maxWidth / 3;                     /* Start glyphs 1/3 into glyph bitmap */
  388.     
  389.     /* Get first and last used character code values -- form of font record is 
  390.        different if this is an outline (spline) font than if it's a bitmap font
  391.        Must be done HERE before any alloc */
  392.     if (CIsOutline (numer, denom)) {                                        
  393.         /* Is an outline font, which is terra incognita */
  394.         macFirst = 0;
  395.         macLast = 255;
  396.     } else {                                /*  Normal bitmap font */
  397.         macFirst = (*(MacFontRec **) frH) -> firstChar;
  398.         macLast = (*(MacFontRec **) frH) -> lastChar;
  399.     }
  400.  
  401.     /* Find the minimum and maximum ISO characters in this font */
  402.     if (pMacPriv->privateEncoding) {
  403.         isoFirst = macFirst;
  404.         isoLast = macLast;
  405.     } else for (isoFirst = 255, isoLast = 0, ch = macFirst; ch <= macLast; ++ch)
  406.         if (widthOf (ch) > 0) {
  407.             unsigned isoCH = TOISO (ch);
  408.             
  409.             if (isoCH < isoFirst) isoFirst = isoCH;
  410.             if (isoCH > isoLast)  isoLast = isoCH;
  411.         }
  412.  
  413.     nchars = isoLast - isoFirst + 1;
  414.     bitmapFont -> num_chars = nchars;
  415.     fi = &(pFont -> info);
  416.  
  417.     bitmapFont -> metrics = (CharInfoPtr) xalloc (sizeof (CharInfoRec) * nchars);
  418.     if (!bitmapFont -> metrics) goto memOops;
  419.  
  420.     for (cip = bitmapFont -> metrics, ch = isoFirst; ch <= isoLast; ++cip, ++ch)
  421.         cip -> bits = 0; /* Helps at memOops */
  422.  
  423.     bitmapFont -> encoding = (CharInfoPtr *) xalloc (sizeof (CharInfoPtr *) * nchars);
  424.     if (!bitmapFont -> encoding) goto memOops;
  425.     
  426.     fi -> firstRow = 0;
  427.     fi -> lastRow = 0;
  428.     fi -> firstCol = isoFirst;
  429.     fi -> lastCol = isoLast;
  430.     fi -> fontAscent = FixRound (pMacPriv->pfm->ascent);
  431.     fi -> fontDescent = FixRound (pMacPriv->pfm->descent);
  432.     fi -> allExist = TRUE; 
  433.     
  434.     if (pMacPriv->privateEncoding)
  435.         fi -> defaultCh = macFirst; /* A likely candidate, but who really knows ... */
  436.     else if (isoFirst < 32)
  437.         fi -> defaultCh = isoFirst; /* Non-printing, renders as the empty box */
  438.     else if (isoLast >= 128)
  439.         fi -> defaultCh = 128; /* Non-printing, renders as the empty box */
  440.     else
  441.         fi -> defaultCh = isoFirst;
  442.         
  443.     /* IM Volume 6, 12-7 says: For bitmapped fonts, the ascent line marks the maximum y-value and
  444.        the descent line marks the minimum y-value. For outline fonts, a font designer can
  445.        create individual glyphs that extend above the ascent line or below the descent line. */
  446.  
  447.     if (CIsOutline(numer, denom)) {
  448.         unsigned char isoChars[256], *p;
  449.  
  450.         for (p = isoChars, ch = isoFirst; ch <= isoLast; ++p, ++ch)
  451.             *p = pMacPriv->privateEncoding ? ch : TOMAC (ch);
  452.  
  453.         if ((ret = COutlineMetrics(nchars, isoChars, numer, denom, &yMax, &yMin, NULL, NULL, NULL))) {
  454.             /* Shouldn't happen, do something rational */
  455.             yMin = fi -> fontDescent;
  456.             yMax = fi -> fontAscent;
  457.         } else {
  458.             yMin = -yMin; /* School of hard knocks... */
  459.         }
  460.     } else {
  461.         yMin = fi -> fontDescent;
  462.         yMax = fi -> fontAscent;
  463.     }
  464.     height = yMax + yMin;
  465.  
  466.     digitCount = digitWidths = 0;
  467.  
  468.     bm.bounds.left = bm.bounds.top = 0;
  469.     bm.bounds.bottom = height;
  470.     bm.bounds.right = maxWidth;
  471.     bm.rowBytes = BYTES_PER_ROW(maxWidth, glyph); /* Must be even! see MacRenderFont*/
  472.  
  473.     if (pMacPriv->forceMono) Mwidth = widthOf ('M');
  474.     
  475.     bm.baseAddr = (Ptr) xalloc (bm.rowBytes * height); /* Space for glyphs to be drawn in */
  476.     if (!bm.baseAddr) goto memOops;
  477.     bzero (bm.baseAddr, bm.rowBytes * height);
  478.  
  479.     PortSize (bm.bounds.right, bm.bounds.bottom);
  480.     SetPortBits (&bm);
  481.  
  482.     bmcip.metrics.ascent = yMax;
  483.     bmcip.metrics.descent = yMin;
  484.     bmcip.metrics.leftSideBearing = -bmorg;
  485.     bmcip.metrics.rightSideBearing = maxWidth - bmorg;
  486.     bmcip.metrics.characterWidth = maxWidth; /* for the sake of completeness */
  487.     bmcip.metrics.attributes = 0; /* for the sake of completeness */
  488.     bmcip.bits = bm.baseAddr;
  489.  
  490.     for (cip = bitmapFont -> metrics, enc = bitmapFont -> encoding, ch = isoFirst; 
  491.          ch <= isoLast; 
  492.          ++ch, ++enc, ++cip) {
  493.         int macCH = pMacPriv->privateEncoding ? ch : TOMAC (ch);
  494.  
  495.         /* Take care not to lock up the UI for too long. (This is
  496.            especially important when querying all fonts with info
  497.            as we have to render all characters to get the info!) */
  498.         if ((ch & 0x3F) == 0)
  499.             MacCheckUI();
  500.         
  501.         *enc = cip;
  502.  
  503.         cip -> metrics.attributes = 0;
  504.         cip -> metrics.characterWidth = widthOf (macCH);
  505.         if (cip -> metrics.characterWidth <= 0) {
  506.             cip -> metrics.ascent = 0;
  507.             cip -> metrics.descent = 0;
  508.             cip -> metrics.leftSideBearing = 0;
  509.             cip -> metrics.rightSideBearing = 0;
  510.             cip -> metrics.characterWidth = 0;
  511.             cip -> bits = NULL;
  512.             fi -> allExist = FALSE;
  513.             continue;
  514.         }
  515.         /* Make sure advance width is constant if forceMono is set */
  516.         if (pMacPriv->forceMono) cip -> metrics.characterWidth = Mwidth;
  517.  
  518.         EraseRect (&bm.bounds);
  519.         MoveTo (bmorg, yMax);    /* Leave a margin to the left of glyph origin */
  520.         DrawChar (macCH);
  521.  
  522.         /* Now find tight left and right bearings by examining the bits in the bm bitmap */
  523.         if (maxWidth == 32) 
  524.             FastCharInkMetrics32(pFont, &bmcip, &bmink);
  525.         else if (maxWidth == 64) 
  526.             FastCharInkMetrics64(pFont, &bmcip, &bmink);
  527.         else 
  528.             FontCharInkMetrics(pFont, &bmcip, &bmink);
  529.  
  530.         /* Some characters (e.g. 'space') have no inked bits, but positive characterWidth */
  531.         if (bmink.ascent == 0 && bmink.descent == 0 && 
  532.             bmink.leftSideBearing == bmink.rightSideBearing) {
  533.             cip -> metrics.ascent = 0;
  534.             cip -> metrics.descent = 0;
  535.             cip -> metrics.leftSideBearing = 0;
  536.             cip -> metrics.rightSideBearing = 0;
  537.             cip -> bits = NULL;
  538.             continue;
  539.         }
  540.  
  541. #ifndef notdef
  542.         if (bmcip.metrics.leftSideBearing == bmink.leftSideBearing ||
  543.             bmcip.metrics.rightSideBearing == bmink.rightSideBearing)
  544.             printf("Bumped against bmcip! ch: 0x%x\n", macCH);
  545. #endif
  546.  
  547.         cip -> metrics.ascent = bmink.ascent;
  548.         cip -> metrics.descent = bmink.descent;
  549.         cip -> metrics.leftSideBearing = bmink.leftSideBearing;
  550.         cip -> metrics.rightSideBearing = bmink.rightSideBearing;
  551.  
  552.         srcR.left = bmorg + bmink.leftSideBearing;
  553.         srcR.top = yMax - bmink.ascent;
  554.         srcR.bottom = yMax + bmink.descent;
  555.         srcR.right = bmorg + bmink.rightSideBearing;
  556.  
  557.         /* Set up glyph bitmap descriptor */
  558.         gbm.bounds.left = gbm.bounds.top = 0;
  559.         gbm.bounds.bottom = cip -> metrics.ascent + cip -> metrics.descent;
  560.         gbm.bounds.right = cip -> metrics.rightSideBearing - cip -> metrics.leftSideBearing;
  561.         gbm.rowBytes = BYTES_PER_ROW(gbm.bounds.right, glyph); /* Must be even! see MacRenderFont */
  562.         gbmSize = gbm.rowBytes * (gbm.bounds.bottom - gbm.bounds.top);
  563.         gbm.baseAddr = (Ptr) xalloc(gbmSize);
  564.         if (!gbm.baseAddr) goto memOops;
  565.  
  566.         bzero(gbm.baseAddr, gbmSize);
  567.         cip -> bits = gbm.baseAddr;
  568.  
  569.         /* Set up destination so that top edge of glyph is butted against the top of */
  570.         /* the font glyph bitmap.  */
  571.  
  572.         dstR.left = dstR.top = 0;
  573.         dstR.bottom = srcR.bottom - srcR.top;
  574.         dstR.right = srcR.right - srcR.left;
  575.  
  576.         /* Copy glyph */
  577.         CopyBits (&bm, &gbm, &srcR, &dstR, srcCopy, (RgnHandle) nil);
  578.  
  579.         if (bit == LSBFirst)
  580.             BitOrderInvert(gbm.baseAddr, gbmSize);
  581.         if (bit != byte) {
  582.             if (scan == 2)
  583.                 TwoByteSwap(gbm.baseAddr, gbmSize);
  584.             else if (scan == 4)
  585.                 FourByteSwap(gbm.baseAddr, gbmSize);
  586.         }
  587.  
  588.         pMacPriv->avgWidth += gbm.bounds.right;
  589.  
  590.         if (ch == 'x')
  591.             pMacPriv->xHeight = bmink.ascent;
  592.  
  593.         if (ch >= '0' && ch <= '9') {
  594.             ++digitCount;
  595.             digitWidths += gbm.bounds.right;
  596.         }
  597.     }
  598.     
  599.     pMacPriv->avgWidth = (nchars ? (pMacPriv->avgWidth * 10)/nchars : 0);
  600.     pMacPriv->quadWidth = 
  601.         (digitCount ? (int)((float) digitWidths / (float) digitCount) : 0);
  602.  
  603.     xfree (bm.baseAddr);
  604.     SetPort (savePort);
  605.     InitCursor ();
  606.     return (Successful);
  607.  
  608. memOops:
  609.     if (bitmapFont -> metrics) {
  610.         for (cip = bitmapFont -> metrics, ch = isoFirst; ch <= isoLast; ++ch, ++cip) {
  611.             if (cip -> bits) xfree(cip -> bits);
  612.         }
  613.         xfree(bitmapFont -> metrics);
  614.     }
  615.     if (bitmapFont -> encoding) xfree(bitmapFont -> encoding);
  616.     if (bm.baseAddr) xfree(bm.baseAddr);
  617.     if (gbm.baseAddr) xfree(gbm.baseAddr);
  618.     return (AllocError);
  619. }
  620.  
  621.