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

  1. /*
  2.  * $XConsortium: bitscale.c,v 1.11 92/05/12 18:07:44 gildea Exp $
  3.  *
  4.  * Copyright 1991 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Keith Packard, MIT X Consortium
  24.  */
  25.  
  26. #include    "fontfilest.h"
  27. #include    "bitmap.h"
  28.  
  29. extern Atom MakeAtom();
  30.  
  31. enum scaleType {
  32.     atom, pixel_size, point_size, resolution_x, resolution_y, average_width,
  33.     scaledX, scaledY, unscaled, scaledXoverY, uncomputed
  34. };
  35.  
  36. typedef struct _fontProp {
  37.     char       *name;
  38.     Atom        atom;
  39.     enum scaleType type;
  40. } fontProp;
  41.  
  42. static unsigned long fontGeneration = 0;    /* initialization flag */
  43.  
  44. static fontProp fontNamePropTable[] = {
  45.     "FOUNDRY", 0, atom,
  46.     "FAMILY_NAME", 0, atom,
  47.     "WEIGHT_NAME", 0, atom,
  48.     "SLANT", 0, atom,
  49.     "SETWIDTH_NAME", 0, atom,
  50.     "ADD_STYLE_NAME", 0, atom,
  51.     "PIXEL_SIZE", 0, pixel_size,
  52.     "POINT_SIZE", 0, point_size,
  53.     "RESOLUTION_X", 0, resolution_x,
  54.     "RESOLUTION_Y", 0, resolution_y,
  55.     "SPACING", 0, atom,
  56.     "AVERAGE_WIDTH", 0, average_width,
  57.     "CHARSET_REGISTRY", 0, atom,
  58.     "CHARSET_ENCODING", 0, atom,
  59.     "FONT", 0, atom
  60. };
  61.  
  62. #define NPROPS ((sizeof(fontNamePropTable) / sizeof(fontProp)) - 1)
  63.  
  64. static fontProp fontPropTable[] = {
  65.     "MIN_SPACE", 0, scaledX,
  66.     "NORM_SPACE", 0, scaledX,
  67.     "MAX_SPACE", 0, scaledX,
  68.     "END_SPACE", 0, scaledX,
  69.     "AVG_CAPITAL_WIDTH", 0, scaledX,
  70.     "AVG_LOWERCASE_WIDTH", 0, scaledX,
  71.     "QUAD_WIDTH", 0, scaledX,
  72.     "FIGURE_WIDTH", 0, scaledX,
  73.     "SUPERSCRIPT_X", 0, scaledX,
  74.     "SUPERSCRIPT_Y", 0, scaledY,
  75.     "SUBSCRIPT_X", 0, scaledX,
  76.     "SUBSCRIPT_Y", 0, scaledY,
  77.     "SUPERSCRIPT_SIZE", 0, scaledY,
  78.     "SUBSCRIPT_SIZE", 0, scaledY,
  79.     "SMALL_CAP_SIZE", 0, scaledY,
  80.     "UNDERLINE_POSITION", 0, scaledY,
  81.     "UNDERLINE_THICKNESS", 0, scaledY,
  82.     "STRIKEOUT_ASCENT", 0, scaledY,
  83.     "STRIKEOUT_DESCENT", 0, scaledY,
  84.     "ITALIC_ANGLE", 0, unscaled,
  85.     "CAP_HEIGHT", 0, scaledY,
  86.     "X_HEIGHT", 0, scaledY,
  87.     "RELATIVE_SETWIDTH", 0, unscaled,
  88.     "RELATIVE_WEIGHT", 0, unscaled,
  89.     "WEIGHT", 0, scaledXoverY,
  90.     "DESTINATION", 0, unscaled
  91. };
  92.  
  93. static void
  94. initFontPropTable()
  95. {
  96.     int         i;
  97.     fontProp   *t;
  98.  
  99.     i = sizeof(fontNamePropTable) / sizeof(fontProp);
  100.     for (t = fontNamePropTable; i; i--, t++)
  101.     t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
  102.  
  103.     i = sizeof(fontPropTable) / sizeof(fontProp);
  104.     for (t = fontPropTable; i; i--, t++)
  105.     t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
  106. }
  107.  
  108. static FontEntryPtr
  109. GetScalableEntry (fpe, name)
  110.     FontPathElementPtr    fpe;
  111.     FontNamePtr        name;
  112. {
  113.     FontDirectoryPtr    dir;
  114.     FontEntryPtr    entry;
  115.  
  116.     dir = (FontDirectoryPtr) fpe->private;
  117.     return FontFileFindNameInDir (&dir->scalable, name);
  118. }
  119.  
  120. static void
  121. ComputeScaleFactors(from, to, dx, dy)
  122.     FontScalablePtr from,
  123.                 to;
  124.     double     *dx,
  125.                *dy;
  126. {
  127.     /* compute scale factors */
  128.     if (to->pixel == from->pixel)
  129.     *dy = 1.0;
  130.     else
  131.     *dy = ((double) to->point * to->y) / (from->point * from->y);
  132.     *dx = (((double) (to->x * from->y)) / (to->y * from->x)) * *dy;
  133.     if (to->width > 0)
  134.     *dx = to->width / (from->width * *dx);
  135. }
  136.  
  137. #define SCORE(m,s) \
  138. if (m >= 1.0) { \
  139.     if (m == 1.0) \
  140.     score += (16 * s); \
  141.     else if (m == 2.0) \
  142.     score += (4 * s); \
  143.     else if (m < minfrac) \
  144.     score += (1 * s); \
  145.     else if (m < 2.0) \
  146.     score += (3 * s); \
  147.     else \
  148.     score += (2 * s); \
  149. } else { \
  150.     m = 1/m; \
  151.     if (m < minfrac) \
  152.     score += (1 * s); \
  153.     else \
  154.     score += (2 * s); \
  155. }
  156.  
  157. FontEntryPtr
  158. FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep)
  159.     FontPathElementPtr    fpe;
  160.     FontEntryPtr    entry;
  161.     FontScalablePtr    vals,
  162.             best;
  163.     double        *dxp,
  164.             *dyp;
  165.     FontPathElementPtr    *fpep;
  166. {
  167.     FontScalableRec temp;
  168.     int            source, i;
  169.     int            best_score,
  170.             score;
  171.     double        dx, dx_amount,
  172.             dy, dy_amount,
  173.             best_dx, best_dx_amount,
  174.             best_dy, best_dy_amount,
  175.             minfrac;
  176.     int            status;
  177.     FontEntryPtr    zero;
  178.     FontNameRec        zeroName;
  179.     char        zeroChars[MAXFONTNAMELEN];
  180.     FontDirectoryPtr    dir;
  181.     FontScaledPtr   scaled;
  182.     FontScalableExtraPtr   extra;
  183.     FontScaledPtr   best_scaled;
  184.     FontPathElementPtr    best_fpe;
  185.  
  186.     /* find the best match */
  187.     best_scaled = 0;
  188.     best_score = 0;
  189.     bcopy (entry->name.name, zeroChars, entry->name.length);
  190.     zeroChars[entry->name.length] = '\0';
  191.     zeroName.name = zeroChars;
  192.     FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO);
  193.     zeroName.length = strlen (zeroChars);
  194.     zeroName.ndashes = entry->name.ndashes;
  195.     /*
  196.      * Look through all the registered bitmap sources for
  197.      * the same zero name as ours; entries along that one
  198.      * can be scaled as desired.
  199.      */
  200.     for (source = 0; source < FontFileBitmapSources.count; source++)
  201.     {
  202.     if (FontFileBitmapSources.fpe[source] == fpe)
  203.         zero = entry;
  204.     else
  205.     {
  206.         dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
  207.         zero = FontFileFindNameInDir (&dir->scalable, &zeroName);
  208.         if (!zero)
  209.         continue;
  210.     }
  211.     extra = zero->u.scalable.extra;
  212.     for (i = 0; i < extra->numScaled; i++)
  213.     {
  214.         scaled = &extra->scaled[i];
  215.         if (!scaled->bitmap)
  216.         continue;
  217.         if ((scaled->vals.pixel <= 0) || (scaled->vals.point <= 0) ||
  218.             (scaled->vals.x <= 0) || (scaled->vals.y <= 0))
  219.             continue;
  220.         ComputeScaleFactors(&scaled->vals, vals, &dx, &dy);
  221.         minfrac = (double) (3 * scaled->vals.pixel);
  222.         minfrac = (minfrac + 4.0) / minfrac;
  223.         score = 0;
  224.         dx_amount = dx;
  225.         dy_amount = dy;
  226.         SCORE(dy_amount, 10);
  227.         SCORE(dx_amount, 1);
  228.         if ((score > best_score) ||
  229.             ((score == best_score) &&
  230.              ((dy_amount < best_dy_amount) ||
  231.                ((dy_amount == best_dy_amount) &&
  232.                 (dx_amount < best_dx_amount))))) 
  233.         {
  234.         best_fpe = FontFileBitmapSources.fpe[source];
  235.             best_scaled = scaled;
  236.             best_score = score;
  237.             best_dx = dx;
  238.             best_dy = dy;
  239.             best_dx_amount = dx_amount;
  240.             best_dy_amount = dy_amount;
  241.         }
  242.     }
  243.     }
  244.     if (!best_scaled)
  245.     return NULL;
  246.  
  247.     *best = best_scaled->vals;
  248.     *fpep = best_fpe;
  249.     *dxp = best_dx;
  250.     *dyp = best_dy;
  251.     return best_scaled->bitmap;
  252. }
  253.  
  254. static int
  255. computeProps(pf, wasStringProp, npf, isStringProp, nprops, xfactor, yfactor)
  256.     FontPropPtr pf;
  257.     char    *wasStringProp;
  258.     FontPropPtr npf;
  259.     char    *isStringProp;
  260.     unsigned int nprops;
  261.     double      xfactor,
  262.                 yfactor;
  263. {
  264.     int         n;
  265.     int         count;
  266.     fontProp   *t;
  267.  
  268.     for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) {
  269.     n = sizeof(fontPropTable) / sizeof(fontProp);
  270.     for (t = fontPropTable; n && (t->atom != pf->name); n--, t++);
  271.     if (!n)
  272.         continue;
  273.  
  274.     switch (t->type) {
  275.     case scaledX:
  276.         npf->value = xfactor * pf->value;
  277.         break;
  278.     case scaledY:
  279.         npf->value = yfactor * pf->value;
  280.         break;
  281.     case unscaled:
  282.         npf->value = pf->value;
  283.         break;
  284.     case scaledXoverY:
  285.         npf->value = pf->value * (xfactor / yfactor);
  286.     }
  287.     npf->name = pf->name;
  288.     npf++;
  289.     count++;
  290.     *isStringProp++ = *wasStringProp;
  291.     }
  292.     return count;
  293. }
  294.  
  295. static int
  296. ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, pProps, pIsStringProp)
  297.     FontInfoPtr     sourceFontInfo;    /* the font to be scaled */
  298.     char        *name;        /* name of resulting font */
  299.     FontScalablePtr vals;
  300.     double        dx,
  301.             dy;        /* scale factors in x and y directions */
  302.     FontPropPtr        *pProps;    /* returns properties; preallocated */
  303.     char        **pIsStringProp;  /* return booleans; preallocated */
  304. {
  305.     int         n;
  306.     char       *ptr1,
  307.                *ptr2;
  308.     FontPropPtr fp;
  309.     fontProp   *fpt;
  310.     extern int  serverGeneration;
  311.     char    *isStringProp;
  312.     int        nProps;
  313.  
  314.     if (fontGeneration != serverGeneration) {
  315.     initFontPropTable();
  316.     fontGeneration = serverGeneration;
  317.     }
  318.     nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp);
  319.     fp = (FontPropPtr) xalloc(sizeof(FontPropRec) * nProps);
  320.     *pProps = fp;
  321.     if (!fp)
  322.     return 1;
  323.     isStringProp = (char *) xalloc (nProps);
  324.     *pIsStringProp = isStringProp;
  325.     if (!isStringProp)
  326.     {
  327.     xfree (fp);
  328.     return 1;
  329.     }
  330.     ptr2 = name;
  331.     for (fpt = fontNamePropTable, n = NPROPS;
  332.      n;
  333.       fp++, fpt++, n--, isStringProp++)
  334.     {
  335.  
  336.     ptr1 = ptr2 + 1;
  337.     if (*ptr1 == '-')
  338.         ptr2 = ptr1;
  339.     else {
  340.         if (n > 1)
  341.         ptr2 = index(ptr1 + 1, '-');
  342.         else
  343.         ptr2 = index(ptr1 + 1, '\0');
  344.     }
  345.  
  346.     *isStringProp = 0;
  347.     switch (fpt->type) {
  348.     case atom:
  349.         fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE);
  350.         *isStringProp = 1;
  351.         break;
  352.     case pixel_size:
  353.         fp->value = vals->pixel;
  354.         break;
  355.     case point_size:
  356.         fp->value = vals->point;
  357.         break;
  358.     case resolution_x:
  359.         fp->value = vals->x;
  360.         break;
  361.     case resolution_y:
  362.         fp->value = vals->y;
  363.         break;
  364.     case average_width:
  365.         fp->value = vals->width;
  366.         break;
  367.     }
  368.     fp->name = fpt->atom;
  369.     }
  370.     n = NPROPS;
  371.     fp->name = fpt->atom;
  372.     fp->value = MakeAtom(name, strlen(name), TRUE);
  373.     *isStringProp = 1;
  374.     isStringProp++;
  375.     fp++;
  376.     n++;
  377.     n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
  378.               fp, isStringProp,
  379.               sourceFontInfo->nprops, dx, dy);
  380.     return n;
  381. }
  382.  
  383. static void ScaleBitmap();
  384.  
  385. /*
  386.  *  ScaleFont
  387.  *  returns a pointer to the new scaled font, or NULL (due to AllocError).
  388.  */
  389. FontPtr
  390. ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp)
  391.     FontPtr     opf;        /* originating font */
  392.     double      widthMult;    /* glyphs width scale factor */
  393.     double      heightMult;    /* glyphs height scale factor */
  394.     FontPropPtr props;        /* the new properties */
  395.     int         propCount;    /* count of new properties */
  396.     char    *isStringProp;    /* booleans per new property */
  397. {
  398.     FontPtr     pf;
  399.     FontInfoPtr pfi,
  400.                 opfi;
  401.     BitmapFontPtr  bitmapFont,
  402.                 obitmapFont;
  403.     CharInfoPtr pci,
  404.                 opci;
  405.     int         nchars;        /* how many characters in the font */
  406.     int         newWidth,
  407.                 newHeight;
  408.     char       *glyphBytes;
  409.     unsigned    bytestoalloc;
  410.     int        *scratch;
  411.     xCharInfo  *pink;
  412.     int         i;
  413.     int         glyph;
  414.  
  415.     extern int  bitmapGetBitmaps();
  416.     extern int  bitmapGetExtents();
  417.     extern int  bitmapGetGlyphs();
  418.     extern int  bitmapGetMetrics();
  419.     extern void bitmapUnloadScalable();
  420.  
  421.     opfi = &opf->info;
  422.     glyph = opf->glyph;
  423.     obitmapFont = (BitmapFontPtr) opf->fontPrivate;
  424.  
  425.     bitmapFont = 0;
  426.     pf = (FontPtr) xalloc(sizeof(FontRec));
  427.     if (!pf)
  428.     goto bail;
  429.     pf->refcnt = 0;
  430.     pf->maxPrivate = -1;
  431.     pf->devPrivates = (pointer *) 0;
  432.     pf->bit = opf->bit;
  433.     pf->byte = opf->byte;
  434.     pf->glyph = opf->glyph;
  435.     pf->scan = opf->scan;
  436.  
  437.     pf->get_glyphs = bitmapGetGlyphs;
  438.     pf->get_metrics = bitmapGetMetrics;
  439.     pf->unload_font = bitmapUnloadScalable;
  440.  
  441.     pfi = &pf->info;
  442.     *pfi = *opfi;
  443.     bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec));
  444.     if (!bitmapFont)
  445.     goto bail;
  446.     nchars = (opf->info.lastRow - opf->info.firstRow + 1) *
  447.     (opf->info.lastCol - opf->info.firstCol + 1);
  448.     pf->fontPrivate = (pointer) bitmapFont;
  449.     bitmapFont->version_num = obitmapFont->version_num;
  450.     bitmapFont->num_chars = obitmapFont->num_chars;
  451.     bitmapFont->num_tables = obitmapFont->num_tables;
  452.     bitmapFont->metrics = 0;
  453.     bitmapFont->ink_metrics = 0;
  454.     bitmapFont->bitmaps = 0;
  455.     bitmapFont->encoding = 0;
  456.     bitmapFont->bitmapExtra = 0;
  457.     bitmapFont->pDefault = 0;
  458.     bitmapFont->metrics = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec));
  459.     if (!bitmapFont->metrics)
  460.     goto bail;
  461.     if (obitmapFont->pDefault)
  462.     bitmapFont->pDefault = bitmapFont->metrics + (obitmapFont->pDefault - obitmapFont->metrics);
  463.     if (obitmapFont->ink_metrics) {
  464.     bitmapFont->ink_metrics = (xCharInfo *) xalloc(nchars * sizeof(xCharInfo));
  465.     if (!bitmapFont->ink_metrics)
  466.         goto bail;
  467.     }
  468.     bitmapFont->encoding = (CharInfoPtr *) xalloc(nchars * sizeof(CharInfoPtr));
  469.     if (!bitmapFont->encoding)
  470.     goto bail;
  471.  
  472.     bytestoalloc = 0;
  473.  
  474. #define MAXSHORT    32767
  475. #define MINSHORT    -32768
  476.  
  477.     pfi->anamorphic = FALSE;
  478.     if (heightMult != widthMult)
  479.     pfi->anamorphic = TRUE;
  480.  
  481.     newHeight = (opfi->fontAscent + opfi->fontDescent) * heightMult;
  482.     pfi->fontAscent = opfi->fontAscent * heightMult;
  483.     pfi->fontDescent = newHeight - pfi->fontAscent;
  484.  
  485.     pfi->minbounds.leftSideBearing = MAXSHORT;
  486.     pfi->minbounds.rightSideBearing = MAXSHORT;
  487.     pfi->minbounds.ascent = MAXSHORT;
  488.     pfi->minbounds.descent = MAXSHORT;
  489.     pfi->minbounds.characterWidth = MAXSHORT;
  490.  
  491.     pfi->maxbounds.leftSideBearing = MINSHORT;
  492.     pfi->maxbounds.rightSideBearing = MINSHORT;
  493.     pfi->maxbounds.ascent = MINSHORT;
  494.     pfi->maxbounds.descent = MINSHORT;
  495.     pfi->maxbounds.characterWidth = MINSHORT;
  496.  
  497.     pci = bitmapFont->metrics;
  498.     for (i = 0; i < nchars; i++)
  499.     {
  500.     if (opci = obitmapFont->encoding[i])
  501.     {
  502.         bitmapFont->encoding[i] = pci;
  503.         newWidth = GLYPHWIDTHPIXELS(opci) * widthMult;
  504.         newHeight = GLYPHHEIGHTPIXELS(opci) * heightMult;
  505.         if (newHeight == 0)
  506.             newHeight = 1;
  507.         if (newWidth == 0)
  508.             newWidth = 1;
  509.     
  510.         pci->metrics.leftSideBearing = (opci->metrics.leftSideBearing *
  511.                         widthMult);
  512.         pci->metrics.rightSideBearing = newWidth +
  513.             pci->metrics.leftSideBearing;
  514.         pci->metrics.ascent = opci->metrics.ascent * heightMult;
  515.         pci->metrics.descent = newHeight - pci->metrics.ascent;
  516.         pci->metrics.characterWidth = opci->metrics.characterWidth * widthMult;
  517.         pci->metrics.attributes = opci->metrics.attributes;
  518.     
  519.         bytestoalloc += BYTES_FOR_GLYPH(pci, glyph);
  520. #define MINMAX(field) \
  521.         if (pfi->minbounds.field > pci->metrics.field) \
  522.             pfi->minbounds.field = pci->metrics.field; \
  523.         if (pfi->maxbounds.field < pci->metrics.field) \
  524.             pfi->maxbounds.field = pci->metrics.field
  525.     
  526.         MINMAX(leftSideBearing);
  527.         MINMAX(rightSideBearing);
  528.         MINMAX(ascent);
  529.         MINMAX(descent);
  530.         MINMAX(characterWidth);
  531. #undef MINMAX
  532.         pci++;
  533.     }
  534.     else
  535.         bitmapFont->encoding[i] = 0;
  536.     }
  537.     bitmapFont->bitmaps = (char *) xalloc(bytestoalloc);
  538.     if (!bitmapFont->bitmaps)
  539.     goto bail;
  540.     bzero(bitmapFont->bitmaps, bytestoalloc);
  541.  
  542.     /* Copy over the scaled XLFD properties */
  543.  
  544.     pfi->props = props;
  545.     pfi->nprops = propCount;
  546.     pfi->isStringProp = isStringProp;
  547.  
  548.     /*
  549.      * For each character, set the per-character metrics, scale the glyph, and
  550.      * check per-font minbounds and maxbounds character information.
  551.      */
  552.  
  553.     glyphBytes = bitmapFont->bitmaps;
  554.     pci = bitmapFont->metrics;
  555.     if (widthMult == 1 && heightMult == 1)
  556.     {
  557.     for (i = 0; i < nchars; i++)
  558.     {
  559.         if (opci = obitmapFont->encoding[i])
  560.         {
  561.         int size;
  562.         xCharInfo   *opink;
  563.  
  564.             pci = bitmapFont->encoding[i];
  565.             if (pink = bitmapFont->ink_metrics)
  566.             {
  567.             pink = pink + (pci - bitmapFont->metrics);
  568.             opink = obitmapFont->ink_metrics;
  569.             opink = opink + (opci - obitmapFont->metrics);
  570.             *pink = *opink;
  571.             }
  572.             pci->bits = glyphBytes;
  573.         size = BYTES_FOR_GLYPH(pci, glyph);
  574.         bcopy (opci->bits, pci->bits, size);
  575.             glyphBytes += size;
  576.         }
  577.     }
  578.     }
  579.     else
  580.     {
  581.         /* Allocate the scratch space for the glyph scaling routine. */
  582.         scratch = (int *)
  583.         xalloc((int) ((opfi->maxbounds.rightSideBearing -
  584.                       opfi->minbounds.leftSideBearing)
  585.                     * widthMult * sizeof(int)));
  586.         if (!scratch)
  587.         goto bail;
  588.     
  589.         pink = bitmapFont->ink_metrics;
  590.         if (pink) {
  591.         pfi->ink_minbounds.leftSideBearing = MAXSHORT;
  592.         pfi->ink_minbounds.rightSideBearing = MAXSHORT;
  593.         pfi->ink_minbounds.ascent = MAXSHORT;
  594.         pfi->ink_minbounds.descent = MAXSHORT;
  595.         pfi->ink_minbounds.characterWidth = MAXSHORT;
  596.         pfi->ink_maxbounds.leftSideBearing = MINSHORT;
  597.         pfi->ink_maxbounds.rightSideBearing = MINSHORT;
  598.         pfi->ink_maxbounds.ascent = MINSHORT;
  599.         pfi->ink_maxbounds.descent = MINSHORT;
  600.         pfi->ink_maxbounds.characterWidth = MINSHORT;
  601.         } else {
  602.         pfi->ink_minbounds = pfi->minbounds;
  603.         pfi->ink_maxbounds = pfi->maxbounds;
  604.         }
  605.     
  606.         for (i = 0; i < nchars; i++)
  607.         {
  608.         if (opci = obitmapFont->encoding[i])
  609.         {
  610.             pci = bitmapFont->encoding[i];
  611.             if (pink = bitmapFont->ink_metrics)
  612.             {
  613.             pink = pink + (pci - bitmapFont->metrics);
  614.             }
  615.             pci->bits = glyphBytes;
  616.             ScaleBitmap (pf, opci, pci, scratch, pink);
  617.             glyphBytes += BYTES_FOR_GLYPH(pci, glyph);
  618.         }
  619.         }
  620.     FontComputeInfoAccelerators (pfi);
  621.         xfree(scratch);
  622.     }
  623.  
  624.     if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) {
  625.     int         r,
  626.                 c,
  627.                 cols;
  628.  
  629.     r = pfi->defaultCh >> 8;
  630.     c = pfi->defaultCh & 0xFF;
  631.     if (pfi->firstRow <= r && r <= pfi->lastRow &&
  632.         pfi->firstCol <= c && c <= pfi->lastCol) {
  633.         cols = pfi->lastCol - pfi->firstCol + 1;
  634.         r = r - pfi->firstRow;
  635.         c = c - pfi->firstCol;
  636.         bitmapFont->pDefault = bitmapFont->encoding[r * cols + c];
  637.     }
  638.     }
  639.  
  640.     return pf;
  641. bail:
  642.     if (pf)
  643.     xfree(pf);
  644.     if (bitmapFont) {
  645.     xfree(bitmapFont->metrics);
  646.     xfree(bitmapFont->ink_metrics);
  647.     xfree(bitmapFont->bitmaps);
  648.     xfree(bitmapFont->encoding);
  649.     }
  650.     return NULL;
  651. }
  652.  
  653. static int
  654. lcm(a, b)            /* least common multiple */
  655.     int         a,
  656.                 b;
  657. {
  658.     register int m;
  659.     register int larger,
  660.                 smaller;
  661.  
  662.     if (a > b) {
  663.     m = larger = a;
  664.     smaller = b;
  665.     } else {
  666.     m = larger = b;
  667.     smaller = a;
  668.     }
  669.  
  670.     while (m % smaller)
  671.     m += larger;
  672.     return m;
  673. }
  674.  
  675. static void
  676. ScaleBitmap(pFont, opci, pci, scratch, pink)
  677.     FontPtr     pFont;
  678.     CharInfoPtr opci;
  679.     CharInfoPtr pci;
  680.     int        *scratch;
  681.     xCharInfo  *pink;
  682. {
  683.     char       *bitmap,
  684.                *newBitmap;
  685.     int         width,
  686.                 height,
  687.                 newWidth,
  688.                 newHeight;
  689.     int         kcounter;    /* 0 <= kcounter <= k */
  690.     int         lcounter;    /* 0 <= lcounter <= l */
  691.     int         kkcounter;    /* 0 <= kkcounter <= kk */
  692.     int         llcounter;    /* 0 <= llcounter <= ll */
  693.     int         newBit;        /* newBitmap column index, by bits */
  694.     int        *acc;        /* pseudonym for scratch */
  695.     int         bitValue;    /* tmp variable */
  696.     int         dataByte;
  697.     char       *dataBytePointer;
  698.     char       *saveDataBytePointer;
  699.  
  700.     /* The following variables have constant values, once assigned. */
  701.  
  702.     int         virtualWidth;    /* unpadded bit width of the virtual bitmap */
  703.     int         virtualHeight;    /* unpadded bit height of the virtual bitmap */
  704.     int         k;        /* horizontal bit copies in virtualBitmap */
  705.     int         l;        /* vertical bit copies in virtualBitmap */
  706.     int         kk;        /* horiz. virtual bits in a newBitmap bit */
  707.     int         ll;        /* vertical virtual bits in a newBitmap bit */
  708.     int         threshold;
  709.     int         padWidth;    /* actual width in bytes of pad in bitmap */
  710.     int         newPadWidth;
  711.  
  712.     bitmap = opci->bits;
  713.     newBitmap = pci->bits;
  714.     width = GLYPHWIDTHPIXELS(opci);
  715.     height = GLYPHHEIGHTPIXELS(opci);
  716.     newWidth = GLYPHWIDTHPIXELS(pci);
  717.     newHeight = GLYPHHEIGHTPIXELS(pci);
  718.     if (!newWidth || !newHeight || !width || !height)
  719.     return;
  720.  
  721.     padWidth = BYTES_PER_ROW(width, pFont->glyph) - ((width + 7) >> 3);
  722.     newPadWidth = BYTES_PER_ROW(newWidth, pFont->glyph) - ((newWidth + 7) >> 3);
  723.     virtualWidth = lcm(width, newWidth);
  724.     virtualHeight = lcm(height, newHeight);
  725.     k = virtualWidth / width;
  726.     l = virtualHeight / height;
  727.     kk = virtualWidth / newWidth;
  728.     ll = virtualHeight / newHeight;
  729.     threshold = kk * ll;
  730.     if (pink) {
  731.     pink->leftSideBearing = MAXSHORT;
  732.     pink->rightSideBearing = MINSHORT;
  733.     pink->ascent = MINSHORT;
  734.     pink->descent = MINSHORT;
  735.     pink->characterWidth = pci->metrics.characterWidth;
  736.     pink->attributes = pci->metrics.attributes;
  737.     }
  738.     saveDataBytePointer = bitmap;
  739.     newBitmap--;
  740.     lcounter = l;
  741.     for (; newHeight; newHeight--, newBitmap += newPadWidth) {
  742.  
  743.     newBit = newWidth;
  744.     acc = scratch;
  745.     do
  746.         *acc++ = threshold;
  747.     while (--newBit);
  748.  
  749.     llcounter = ll;
  750.     while (llcounter) {
  751.         int         bit;    /* index into glyph row, indicating a bit */
  752.         int         row_dup;/* row duplication count from source */
  753.         int         kdup;
  754.         int         kkdup;
  755.  
  756.         if (!lcounter) {
  757.         lcounter = l;
  758.         dataBytePointer += padWidth;
  759.         saveDataBytePointer = dataBytePointer;
  760.         } else
  761.         dataBytePointer = saveDataBytePointer;
  762.  
  763.         if ((row_dup = llcounter) > lcounter)
  764.         row_dup = lcounter;
  765.         lcounter -= row_dup;
  766.         llcounter -= row_dup;
  767.         row_dup <<= 1;
  768.  
  769.         bit = 1;
  770.         kdup = k * row_dup;
  771.         kkdup = kk * row_dup;
  772.         kcounter = 0;
  773.         newBit = newWidth;
  774.         acc = scratch;
  775.         do {
  776.         int         tmp = 0;
  777.  
  778.         kkcounter = kkdup;
  779.         if (!kcounter) {
  780.             /* advance to the next column of the source bitmap */
  781.             kcounter = kdup;
  782.             if (!(--bit)) {
  783.             bit = 8;
  784.             dataByte = *dataBytePointer++;
  785.             }
  786.             /* extract the appropriate bit from source bitmap */
  787.             if (pFont->bit == LSBFirst) {
  788.             bitValue = dataByte & 1;
  789.             dataByte >>= 1;
  790.             } else {
  791.             bitValue = dataByte & 128;
  792.             dataByte <<= 1;
  793.             }
  794.         }
  795.         while ((kkcounter -= kcounter) > 0) {
  796.             if (bitValue)
  797.             tmp += kcounter;
  798.             /* advance to the next column of the source bitmap */
  799.             kcounter = kdup;
  800.             if (!(--bit)) {
  801.             bit = 8;
  802.             dataByte = *dataBytePointer++;
  803.             }
  804.             /* extract the appropriate bit from source bitmap */
  805.             if (pFont->bit == LSBFirst) {
  806.             bitValue = dataByte & 1;
  807.             dataByte >>= 1;
  808.             } else {
  809.             bitValue = dataByte & 128;
  810.             dataByte <<= 1;
  811.             }
  812.         }
  813.         if (bitValue)
  814.             tmp += kcounter + kkcounter;
  815.         kcounter = -kkcounter;
  816.         *acc++ -= tmp;
  817.         }
  818.         while (--newBit);
  819.     }
  820.     /*
  821.      * Set the appropriate bits in newBitmap, based on the count of bits
  822.      * set in the virtual bitmap which map to a single bit in the new
  823.      * bitmap, and based on the knowing the constant number of bits in the
  824.      * virtual bitmap which map to a bit in the new bitmap.
  825.      */
  826.     acc = scratch;
  827.  
  828.     if (pFont->bit == LSBFirst)
  829.         bitValue = 128;
  830.     else
  831.         bitValue = 1;
  832.     newBit = newWidth;
  833.     do {
  834.         if (pFont->bit == LSBFirst) {
  835.         if ((bitValue <<= 1) == 256) {
  836.             bitValue = 0x1;
  837.             newBitmap++;
  838.         }
  839.         } else {
  840.         if (!(bitValue >>= 1)) {
  841.             bitValue = 128;
  842.             newBitmap++;
  843.         }
  844.         }
  845.         if (*acc++ < 0)
  846.         *newBitmap |= bitValue;
  847.     } while (--newBit);
  848.     if (pink) {
  849.         for (acc = scratch, newBit = newWidth;
  850.             --newBit >= 0 && *acc++ >= 0;
  851.         );
  852.         if (newBit >= 0) {
  853.         if (newHeight >= pink->ascent)
  854.             pink->ascent = newHeight;
  855.         pink->descent = newHeight;
  856.         newBit = pci->metrics.leftSideBearing + newWidth - newBit - 1;
  857.         if (newBit < pink->leftSideBearing)
  858.             pink->leftSideBearing = newBit;
  859.         }
  860.         for (acc = scratch + newWidth, newBit = newWidth;
  861.             --newBit >= 0 && *--acc >= 0;
  862.         );
  863.         if (newBit >= 0)
  864.         {
  865.             newBit = pci->metrics.leftSideBearing + newBit + 1;
  866.             if (newBit > pink->rightSideBearing)
  867.             pink->rightSideBearing = newBit;
  868.         }
  869.     }
  870.     }
  871. #define MINMAX(field) \
  872.     if (pFont->info.ink_minbounds.field > pink->field) \
  873.     pFont->info.ink_minbounds.field = pink->field; \
  874.     if (pFont->info.ink_maxbounds.field < pink->field) \
  875.     pFont->info.ink_maxbounds.field = pink->field
  876.  
  877.     if (pink) {
  878.     if (pink->ascent == MINSHORT)
  879.     {
  880.         /* hack to make computation below work */
  881.         pink->ascent = pci->metrics.descent;
  882.         /* these would also have not been set as this character is empty */
  883.         pink->descent = pink->ascent + 1;
  884.         pink->leftSideBearing = 0;
  885.         pink->rightSideBearing = 0;
  886.     }
  887.     height = pink->ascent - pink->descent + 1;
  888.     pink->ascent = pci->metrics.ascent -
  889.         (GLYPHHEIGHTPIXELS(pci) - pink->ascent);
  890.     pink->descent = height - pink->ascent;
  891.     MINMAX(leftSideBearing);
  892.     MINMAX(rightSideBearing);
  893.     MINMAX(ascent);
  894.     MINMAX(descent);
  895.     MINMAX(characterWidth);
  896.     }
  897. #undef MINMAX
  898. }
  899.  
  900. #ifdef NOTDEF
  901. /*
  902.  *    exported interfaces
  903.  */
  904.  
  905. FontFileLoadName(dirs, ndirs, name, pfont, format, fmask)
  906.     FontFileDirPtr *dirs;
  907.     int         ndirs;
  908.     char       *name;
  909.     FontPtr    *pfont;
  910.     fsBitmapFormat format;
  911.     fsBitmapFormatMask fmask;
  912. {
  913.     FontFileNamePtr fname;
  914.     char        full_name[1024];
  915.     int         ret = BadFontName;
  916.     int         i;
  917.  
  918.     i = 0;
  919.     while (i < ndirs) {
  920.     if (fname = FontFileFindNameInDir(dirs[i], name)) {
  921.         if (!fname->alias) {
  922.         if (!fname->font) {
  923.             strcpy(full_name, dirs[i]->dir);
  924.             strcat(full_name, fname->file);
  925.             ret = FontFileLoad(pfont, full_name, format, fmask);
  926.             if (ret == Successful) {
  927.             fname->font = *pfont;
  928.             (*pfont)->fpePrivate = (pointer) fname;
  929.             }
  930.             return ret;
  931.         }
  932.         *pfont = fname->font;
  933.         return Successful;
  934.         }
  935.         name = fname->file;
  936.         i = 0;
  937.     } else
  938.         i++;
  939.     }
  940.     return BadFontName;
  941. }
  942. #endif
  943.  
  944. /* ARGSUSED */
  945. BitmapOpenScalable (fpe, pFont, flags, entry, fileName, vals, format, fmask)
  946.     FontPathElementPtr    fpe;
  947.     FontPtr        *pFont;
  948.     int            flags;
  949.     FontEntryPtr    entry;
  950.     char        *fileName;  /* unused */
  951.     FontScalablePtr    vals;
  952.     fsBitmapFormat    format;
  953.     fsBitmapFormatMask    fmask;
  954. {
  955.     FontScalableRec    best;
  956.     FontPtr        font = NullFont;
  957.     double        dx,
  958.             dy;
  959.     FontPropPtr        props;
  960.     char        *isStringProp;
  961.     int            propCount;
  962.     int            status;
  963.  
  964.     FontEntryPtr    scaleFrom;
  965.     FontPathElementPtr    scaleFPE;
  966.     FontPtr        sourceFont;
  967.     char        fontName[MAXFONTNAMELEN];
  968.  
  969.     /* Can't deal with mix-endian fonts yet */
  970.  
  971. #ifdef NOTDEF /* XXX need better test */
  972.     if ((format & BitmapFormatByteOrderMask) !=
  973.         (format & BitmapFormatBitOrderMask))
  974.     return NullFontFileName;
  975. #endif
  976.  
  977.     scaleFrom = FindBestToScale (fpe, entry, vals, &best, &dx, &dy, &scaleFPE);
  978.     if (!scaleFrom)
  979.     return BadFontName;
  980.  
  981.     status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, format, fmask);
  982.  
  983.     if (status != Successful)
  984.     return BadFontName;
  985.  
  986.     if (!vals->width)
  987.     vals->width = best.width * dx;
  988.  
  989.     /* Prepare font properties for the new font */
  990.  
  991.     strcpy (fontName, scaleFrom->name.name);
  992.     FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE);
  993.  
  994.     propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, dx, dy,
  995.                     &props, &isStringProp);
  996.  
  997.     if (propCount && (!props || !isStringProp))
  998.     return AllocError;
  999.     
  1000.     /* Compute the scaled font */
  1001.  
  1002.     font = ScaleFont(sourceFont, dx, dy, props, propCount, isStringProp);
  1003.  
  1004.     /* Dispose source font */
  1005.  
  1006.     if (!sourceFont->refcnt)
  1007.     FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
  1008.  
  1009.     if (!font)
  1010.     {
  1011.     xfree (props);
  1012.     xfree (isStringProp);
  1013.     return AllocError;
  1014.     }
  1015.     *pFont = font;
  1016.     return Successful;
  1017. }
  1018.  
  1019. static
  1020. ScaleBounds (bounds, dx, dy)
  1021.     xCharInfo    *bounds;
  1022.     double  dx, dy;
  1023. {
  1024.     bounds->leftSideBearing *= dx;
  1025.     bounds->rightSideBearing *= dx;
  1026.     bounds->ascent *= dy;
  1027.     bounds->descent *= dy;
  1028.     bounds->characterWidth *= dx;
  1029. }
  1030.  
  1031. BitmapGetInfoScalable (fpe, pFontInfo, entry, fontName, fileName, vals)
  1032.     FontPathElementPtr    fpe;
  1033.     FontInfoPtr        pFontInfo;
  1034.     FontEntryPtr    entry;
  1035.     FontNamePtr        fontName;
  1036.     char        *fileName;
  1037.     FontScalablePtr    vals;
  1038. {
  1039.     FontEntryPtr    scaleFrom;
  1040.     FontPathElementPtr    scaleFPE;
  1041.     double        dx,
  1042.             dy;
  1043.     FontScalableRec    best;
  1044.     FontInfoRec        scaleInfo;
  1045.     int            ret;
  1046.     int            propCount;
  1047.     FontPropPtr        props;
  1048.     char        *isStringProp;
  1049.  
  1050.     scaleFrom = FindBestToScale (fpe, entry, vals, &best, &dx, &dy, &scaleFPE);
  1051.     if (!scaleFrom)
  1052.     return BadFontName;
  1053.     ret = FontFileGetInfoBitmap (fpe, &scaleInfo, scaleFrom);
  1054.     if (ret != Successful)
  1055.     return ret;
  1056.  
  1057.     if (!vals->width)
  1058.     vals->width = best.width * dx;
  1059.  
  1060.     propCount = ComputeScaledProperties (&scaleInfo, fontName->name, vals, dx, dy,
  1061.                     &props, &isStringProp);
  1062.     xfree (scaleInfo.isStringProp);
  1063.     xfree (scaleInfo.props);
  1064.     if (propCount && (!props || !isStringProp))
  1065.     return AllocError;
  1066.  
  1067.     *pFontInfo = scaleInfo;
  1068.     pFontInfo->props = props;
  1069.     pFontInfo->isStringProp = isStringProp;
  1070.     pFontInfo->nprops = propCount;
  1071.     pFontInfo->fontDescent *= dy;
  1072.     pFontInfo->fontAscent *= dy;
  1073.     ScaleBounds (&pFontInfo->minbounds, dx, dy);
  1074.     ScaleBounds (&pFontInfo->maxbounds, dx, dy);
  1075.     ScaleBounds (&pFontInfo->ink_minbounds, dx, dy);
  1076.     ScaleBounds (&pFontInfo->ink_minbounds, dx, dy);
  1077.     return Successful;
  1078. }
  1079.  
  1080. void
  1081. bitmapUnloadScalable (pFont)
  1082.     FontPtr        pFont;
  1083. {
  1084.     BitmapFontPtr   bitmapFont;
  1085.     FontInfoPtr        pfi;
  1086.  
  1087.     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
  1088.     pfi = &pFont->info;
  1089.     xfree (pfi->props);
  1090.     xfree (pfi->isStringProp);
  1091.     xfree (bitmapFont->encoding);
  1092.     xfree (bitmapFont->bitmaps);
  1093.     xfree (bitmapFont->ink_metrics);
  1094.     xfree (bitmapFont->metrics);
  1095.     xfree (pFont->fontPrivate);
  1096.     xfree (pFont);
  1097. }
  1098.