home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / snf / scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-10  |  24.4 KB  |  904 lines

  1. /* $Header: scale.c,v 1.20 91/01/10 20:09:48 rws Exp $ */
  2.  
  3. /*
  4.  * Copyright 1990 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.  */
  24.  
  25. #include "Xos.h"
  26. #include "X.h"
  27. #include "Xmd.h"
  28. #include "Xproto.h"
  29. #include "dixfont.h"
  30. #include "dixfontstr.h"
  31. #include "font.h"
  32. #include "fontstruct.h"
  33. #include "snfstruct.h"
  34. #include "os.h"
  35. #include "osstruct.h"
  36. #include "misc.h"
  37. #include "fontdir.h"
  38.  
  39. #define MAXFNAMELEN 1024
  40.  
  41. extern FontFile FindFontFile();
  42. extern Atom MakeAtom();
  43.  
  44. typedef struct _scalables {
  45.     int pixel, point, x, y, width;
  46. } Scalables;
  47.  
  48. enum scaleType {
  49.     atom, pixel_size, point_size, resolution_x, resolution_y, average_width,
  50.     scaledX, scaledY, unscaled, scaledXoverY, uncomputed
  51.     };
  52.     
  53. typedef struct _fontProp {
  54.     char            *name;
  55.     Atom        atom;
  56.     enum scaleType    type;
  57. } fontProp;
  58.  
  59.  
  60. static unsigned long fontGeneration=0;        /* initialization flag */
  61.  
  62. static FontTable scaledFonts = (FontTable)NULL;
  63.  
  64. static fontProp fontNamePropTable[] = {
  65.     "FOUNDRY",            0,    atom,
  66.     "FAMILY_NAME",        0,    atom,
  67.     "WEIGHT_NAME",        0,    atom,
  68.     "SLANT",            0,    atom,
  69.     "SETWIDTH_NAME",        0,    atom,
  70.     "ADD_STYLE_NAME",        0,    atom,
  71.     "PIXEL_SIZE",        0,    pixel_size,
  72.     "POINT_SIZE",        0,     point_size,
  73.     "RESOLUTION_X",        0,    resolution_x,
  74.     "RESOLUTION_Y",        0,    resolution_y,
  75.     "SPACING",            0,    atom,
  76.     "AVERAGE_WIDTH",        0,    average_width,
  77.     "CHARSET_REGISTRY",        0,    atom,
  78.     "CHARSET_ENCODING",        0,    atom,
  79.     "FONT",            0,    atom
  80. };
  81. #define NPROPS ((sizeof(fontNamePropTable) / sizeof(fontProp)) - 1)
  82.  
  83. static fontProp fontPropTable[] = {
  84.     "MIN_SPACE",        0,    scaledX,
  85.     "NORM_SPACE",        0,    scaledX,
  86.     "MAX_SPACE",        0,    scaledX,
  87.     "END_SPACE",        0,    scaledX,
  88.     "AVG_CAPITAL_WIDTH",    0,    scaledX,
  89.     "AVG_LOWERCASE_WIDTH",    0,    scaledX,
  90.     "QUAD_WIDTH",        0,    scaledX,
  91.     "FIGURE_WIDTH",        0,    scaledX,
  92.     "SUPERSCRIPT_X",        0,    scaledX,
  93.     "SUPERSCRIPT_Y",        0,    scaledY,
  94.     "SUBSCRIPT_X",        0,    scaledX,
  95.     "SUBSCRIPT_Y",        0,    scaledY,
  96.     "SUPERSCRIPT_SIZE",        0,    scaledY,
  97.     "SUBSCRIPT_SIZE",        0,    scaledY,
  98.     "SMALL_CAP_SIZE",        0,    scaledY,
  99.     "UNDERLINE_POSITION",    0,    scaledY,
  100.     "UNDERLINE_THICKNESS",    0,    scaledY,
  101.     "STRIKEOUT_ASCENT",        0,    scaledY,
  102.     "STRIKEOUT_DESCENT",    0,    scaledY,
  103.     "ITALIC_ANGLE",        0,    unscaled,
  104.     "CAP_HEIGHT",        0,    scaledY,
  105.     "X_HEIGHT",            0,    scaledY,
  106.     "RELATIVE_SETWIDTH",    0,    unscaled,
  107.     "RELATIVE_WEIGHT",        0,    unscaled,
  108.     "WEIGHT",            0,    scaledXoverY,
  109.     "DESTINATION",        0,    unscaled
  110. };
  111.     
  112. static void initFontPropTable()
  113. {
  114.     int        i;
  115.     fontProp *    t;
  116.  
  117.     i = sizeof(fontNamePropTable) / sizeof(fontProp);
  118.     for (t=fontNamePropTable; i; i--, t++)
  119.     t->atom = MakeAtom(t->name, (unsigned)strlen(t->name), TRUE);
  120.  
  121.     i  = sizeof(fontPropTable) / sizeof(fontProp);
  122.     for (t=fontPropTable; i; i--, t++)
  123.     t->atom = MakeAtom(t->name, (unsigned)strlen(t->name), TRUE);
  124. }
  125.  
  126. static char *
  127. GetInt(ptr, val)
  128.     char *ptr;
  129.     int *val;
  130. {
  131.     ptr++;
  132.     if (*ptr == '*')
  133.     {
  134.     *val = -1;
  135.     ptr++;
  136.     }
  137.     else
  138.     for (*val = 0; *ptr >= '0' && *ptr <= '9'; )
  139.         *val = *val * 10 + *ptr++ - '0';
  140.     if (*ptr == '-')
  141.     return ptr;
  142.     return (char *)NULL;
  143. }
  144.  
  145. static Bool
  146. ParseXLFDName(fname, vals, subst)
  147.     char *fname;
  148.     register Scalables *vals;
  149.     char subst;
  150. {
  151.     register char *ptr;
  152.     register char *ptr1, *ptr2, *ptr3, *ptr4;
  153.  
  154.     if (!(*fname == '-') ||                /* foundry */
  155.     !(ptr = index(fname+1, '-')) ||            /* family_name */
  156.     !(ptr = index(ptr+1, '-')) ||            /* weight_name */
  157.     !(ptr = index(ptr+1, '-')) ||            /* slant */
  158.     !(ptr = index(ptr+1, '-')) ||            /* setwidth_name */
  159.     !(ptr = index(ptr+1, '-')) ||            /* add_style_name */
  160.     !(ptr1 = ptr = index(ptr+1, '-')) ||        /* pixel_size */
  161.     !(ptr = GetInt(ptr, &vals->pixel)) ||
  162.     !(ptr = GetInt(ptr, &vals->point)) ||        /* point_size */
  163.     !(ptr = GetInt(ptr, &vals->x)) ||        /* resolution_x */
  164.     !(ptr2 = ptr = GetInt(ptr, &vals->y)) ||    /* resolution_y */
  165.     !(ptr3 = ptr = index(ptr+1, '-')) ||        /* spacing */
  166.     !(ptr4 = ptr = GetInt(ptr, &vals->width)) ||    /* average_width */
  167.     !(ptr = index(ptr+1, '-')) ||            /* charset_registry */
  168.     index(ptr+1, '-'))                /* charset_encoding */
  169.     return FALSE;
  170.     if (subst)
  171.     {
  172.     ptr = ptr1 + 1;
  173.     *ptr++ = subst;
  174.     *ptr++ = '-';
  175.     *ptr++ = subst;
  176.     *ptr++ = '-';
  177.     *ptr++ = subst;
  178.     *ptr++ = '-';
  179.     *ptr++ = subst;
  180.     bcopy(ptr2, ptr, ptr3 - ptr2 + 1);
  181.     ptr += ptr3 - ptr2 + 1;
  182.     *ptr++ = subst;
  183.     strcpy(ptr, ptr4);
  184.     }
  185.     return TRUE;
  186. }
  187.  
  188. static void
  189. ComputeScaleFactors(from, to, dx, dy)
  190.     Scalables *from, *to;
  191.     double *dx, *dy;
  192. {
  193.     /* compute scale factors */
  194.     *dy = ((double) to->point * to->y) / (from->point * from->y);
  195.     *dx = (((double)(to->x * from->y)) / (to->y * from->x)) * *dy;
  196.     if (to->width > 0)
  197.     *dx = to->width / (from->width * *dx);
  198. }
  199.  
  200. #define SCORE(m,s) \
  201. if (m >= 1.0) { \
  202.     if ((m == 1.0) || (m == 2.0)) \
  203.     score += (4 * s); \
  204.     else if (m < minfrac) \
  205.     score += (1 * s); \
  206.     else if (m < 2.0) \
  207.     score += (3 * s); \
  208.     else \
  209.     score += (2 * s); \
  210. } else { \
  211.     m = 1/m; \
  212.     if (m < minfrac) \
  213.     score += (1 * s); \
  214.     else \
  215.     score += (2 * s); \
  216. }
  217.  
  218. static Bool
  219. FindBestToScale(fname, vals, best)
  220.     char *fname;
  221.     register Scalables *vals, *best;
  222. {
  223.     register FontPathPtr fpr;
  224.     Scalables temp;
  225.     int best_path;
  226.     register int i;
  227.     int best_score, score;
  228.     double dx, dy, best_dx, best_dy, minfrac;
  229.  
  230.     /* find all matching fonts */
  231.     fpr = ExpandFontNamePattern((unsigned)strlen(fname), fname, 65535);
  232.     if (!fpr)
  233.     return False;
  234.     /* find the best match */
  235.     best_score = 0;
  236.     for (i = 0; i < fpr->npaths; i++)
  237.     {
  238.     if (!ParseXLFDName(fpr->paths[i], &temp, '\0'))
  239.         continue;
  240.     if ((temp.pixel <= 0) || (temp.point <= 0) ||
  241.         (temp.x <= 0) || (temp.y <= 0))
  242.         continue;
  243.     ComputeScaleFactors(&temp, vals, &dx, &dy);
  244.     minfrac = (double)(3 * temp.pixel);
  245.     minfrac = (minfrac + 4.0) / minfrac;
  246.     score = 0;
  247.     SCORE(dy, 10);
  248.     SCORE(dx, 1);
  249.     if ((score > best_score) ||
  250.         ((score == best_score) &&
  251.          ((dy < best_dy) || ((dy == best_dy) && (dx < best_dx))))) {
  252.         best_path = i;
  253.         best_score = score;
  254.         best_dx = dx;
  255.         best_dy = dy;
  256.         *best = temp;
  257.     }        
  258.     }
  259.     if (best_score)
  260.     strcpy(fname, fpr->paths[best_path]);
  261.     FreeFontRecord(fpr);
  262.     return (best_score != 0);
  263. }
  264.  
  265. static int computeProps(pf, npf, nprops, xfactor, yfactor)
  266.     DIXFontProp *    pf;
  267.     DIXFontProp *    npf;
  268.     unsigned int    nprops;
  269.     double        xfactor, yfactor;
  270. {
  271.     int        n;
  272.     int     count;
  273.     fontProp*    t;
  274.  
  275.     for (count=0; nprops > 0; nprops--, pf++) {
  276.     n = sizeof(fontPropTable) / sizeof(fontProp);
  277.     for (t=fontPropTable; n && (t->atom != pf->name); n--, t++) ;
  278.     if (!n) continue;
  279.  
  280.     switch (t->type) {
  281.       case scaledX:
  282.         npf->value = xfactor * pf->value;
  283.         break;
  284.       case scaledY:
  285.         npf->value = yfactor * pf->value;
  286.         break;
  287.       case unscaled:
  288.         npf->value = pf->value;
  289.         break;
  290.       case scaledXoverY:
  291.         npf->value = pf->value * (xfactor / yfactor);
  292.     }
  293.     npf->name = pf->name;
  294.     npf++;
  295.     count++;
  296.     }
  297.     return count;
  298. }
  299.  
  300. static int ComputeScaledProperties(font, canonname, vals, dx, dy, 
  301.                    scalename, tmpProps)
  302.     FontPtr    font;        /* the font to be scaled */
  303.     char *    canonname;    /* canonical name of the scaled font */
  304.     Scalables    *vals;
  305.     double    dx, dy;        /* scale factors in x and y directions */
  306.     char *    scalename;    /* returns XLFD name of the scaled font */
  307.     DIXFontProp *tmpProps;    /* returns properties; preallocated */
  308. {
  309.     int        n;
  310.     unsigned    len;
  311.     char     *ptr1, *ptr2, *ptr3, *ptr4;
  312.     DIXFontProp *fp;
  313.     fontProp    *fpt;
  314.  
  315.     if (fontGeneration != serverGeneration) {
  316.     initFontPropTable();
  317.     fontGeneration = serverGeneration;
  318.     }
  319.     ptr2 = canonname;
  320.     ptr4 = scalename;
  321.     for (fp=tmpProps, fpt=fontNamePropTable, n=NPROPS; n; fp++, fpt++, n--) {
  322.  
  323.     *ptr4 = '-';
  324.     ptr1 = ptr2+1;
  325.     if (*ptr1 == '-')
  326.         ptr2 = ptr1;
  327.     else {
  328.         if (n > 1)
  329.         ptr2 = index(ptr1+1, '-');
  330.         else
  331.         ptr2 = index(ptr1+1, '\0');
  332.     }
  333.     ptr3 = ptr4+1;
  334.  
  335.     switch (fpt->type) {
  336.       case atom:
  337.         len = ptr2 - ptr1;
  338.         strncpy(ptr3, ptr1, len);
  339.         fp->value = MakeAtom(ptr3, len, TRUE);
  340.         break;
  341.       case pixel_size:
  342.         sprintf(ptr3, "%d", vals->pixel);
  343.         len = strlen(ptr3);
  344.         fp->value = vals->pixel;
  345.         break;
  346.       case point_size:
  347.         sprintf(ptr3, "%d", vals->point);
  348.         len = strlen(ptr3);
  349.         fp->value = vals->point;
  350.         break;
  351.       case resolution_x:
  352.         sprintf(ptr3, "%d", vals->x);
  353.         len = strlen(ptr3);
  354.         fp->value = vals->x;
  355.         break;
  356.       case resolution_y:
  357.         sprintf(ptr3, "%d", vals->y);
  358.         len = strlen(ptr3);
  359.         fp->value = vals->y;
  360.         break;
  361.       case average_width:
  362.         sprintf(ptr3, "%d", vals->width);
  363.         len = strlen(ptr3);
  364.         fp->value = vals->width;
  365.         break;
  366.     }
  367.     ptr4 = ptr3 + len;
  368.     fp->name = fpt->atom;
  369.     }
  370.     *ptr4 = '\0';
  371.     fp->name = fpt->atom;
  372.     fp->value = MakeAtom(scalename, (unsigned)(ptr4 - scalename), TRUE);
  373.  
  374.     n = NPROPS + 1;
  375.     n += computeProps(font->pFP, tmpProps + n, font->pFI->nProps, dx, dy);
  376.     return n;
  377. }
  378.  
  379. /* 
  380.  *  ScaleFont 
  381.  *  returns a pointer to the new scaled font, or NULL (due to BadAlloc).
  382.  */
  383. static FontPtr
  384. ScaleFont(opf, widthMult, heightMult, props, propCount)
  385.     FontPtr    opf;            /* originating font */
  386.     double    widthMult;        /* glyphs width scale factor */
  387.     double    heightMult;        /* glyphs height scale factor */
  388.     DIXFontProp* props;            /* some of the new properties */
  389.     int        propCount;        /* count of new properties */
  390. {
  391.     FontPtr    pf;
  392.     FontInfoPtr    pfi, opfi;
  393.     CharInfoPtr pci, opci;
  394.     int     nchars;            /* how many characters in the font */
  395.     int        newWidth, newHeight;
  396.     unsigned    glyphBytesOffset;
  397.     unsigned    bytestoalloc, bytestoink, bytestoprops, bytestoglyphs;
  398.     char *    fontspace;
  399.     int *    scratch;
  400.     static void    ScaleBitmap();
  401.  
  402.     /* Allocate a new Font struct in one chunk of memory.
  403.      *
  404.      *  FontRec            pf
  405.      *  FontInfoRec        pf->pFI
  406.      *  CharInfoRec's        pf->pCI[i]
  407.      *  Glyphs            pf->pGlyphs[i]     not necessarily the same i
  408.      *  DIX Properties        pf->pFP
  409.      *  Ink CharInfoRec's    pf->pInkCI, pf->pInkMin, pf->pInkMax
  410.      */
  411.     opfi = opf->pFI;
  412.     bytestoalloc = sizeof (FontRec);
  413.     bytestoalloc += BYTESOFFONTINFO(opfi);
  414.     bytestoalloc += BYTESOFCHARINFO(opfi);
  415.     bytestoglyphs = bytestoalloc;
  416.     nchars = n2dChars(opfi);
  417.     for (opci=opf->pCI; nchars; opci++, nchars--)
  418.     if (opci->exists) {
  419.         newWidth = GLYPHWIDTHPIXELS(opci) * widthMult;
  420.         newHeight = GLYPHHEIGHTPIXELS(opci) * heightMult;
  421.         bytestoalloc += PADGLYPHWIDTHBYTES(newWidth) * newHeight;
  422.     }
  423.     nchars = n2dChars(opfi);
  424.     bytestoprops = bytestoalloc;
  425.     bytestoalloc += propCount * sizeof (DIXFontProp);
  426.     bytestoink = bytestoalloc;
  427.     if (opfi->inkMetrics) bytestoalloc += BYTESOFINKINFO(opfi);
  428.  
  429.     /* allocate the new font structure */
  430.  
  431.     if (! (fontspace = (char *) xalloc(bytestoalloc)))
  432.     return (FontPtr) NULL;
  433.  
  434.     /* set up pointers into the new font space */
  435.  
  436.     pf = (FontPtr) fontspace;
  437.     pfi = pf->pFI = (FontInfoPtr) (fontspace + sizeof(FontRec));
  438.     *pfi = *opfi;
  439.     pfi->nProps = propCount;
  440.  
  441.     pf->pCI = ADDRCharInfoRec(pfi);
  442.     pf->pGlyphs = (char *) (fontspace + bytestoglyphs);
  443.     bzero(pf->pGlyphs, (bytestoprops - bytestoglyphs));
  444.  
  445.     /* Copy over the scaled XLFD properties */
  446.  
  447.     pf->pFP = (DIXFontProp *) (fontspace + bytestoprops);
  448.     bcopy((char *)props, (char *)pf->pFP, propCount * sizeof(DIXFontProp));
  449.  
  450.     if (pfi->inkMetrics) {
  451.     pf->pInkMin = (CharInfoPtr)(fontspace + bytestoink);
  452.     pf->pInkMax = pf->pInkMin + 1;
  453.     pf->pInkCI = pf->pInkMax + 1;
  454.     } else {
  455.     pf->pInkMin = &pfi->minbounds;
  456.     pf->pInkMax = &pfi->maxbounds;
  457.     pf->pInkCI = pf->pCI;
  458.     }
  459.  
  460.     /* FontRec */
  461.  
  462.     pf->osPrivate = opf->osPrivate;
  463.     pf->fileType = opf->fileType;
  464.     pf->refcnt = 0;
  465.  
  466.     /* FontInfo
  467.      *    fontDescent
  468.      *  fontAscent
  469.      *  minbounds
  470.      *  maxbounds
  471.      *  --  everything else was copied from the original font, above.
  472.      */
  473.  
  474.     pfi->fontDescent *= heightMult;
  475.     pfi->fontAscent  *= heightMult;
  476.     pfi->minbounds.metrics.leftSideBearing = MAXSHORT;
  477.     pfi->minbounds.metrics.rightSideBearing = MAXSHORT;
  478.     pfi->minbounds.metrics.ascent = MAXSHORT;
  479.     pfi->minbounds.metrics.descent = MAXSHORT;
  480.     pfi->minbounds.metrics.characterWidth = opf->pCI->metrics.characterWidth;
  481.  
  482.     pfi->maxbounds.metrics.leftSideBearing = MINSHORT;
  483.     pfi->maxbounds.metrics.rightSideBearing = MINSHORT;
  484.     pfi->maxbounds.metrics.ascent = MINSHORT;
  485.     pfi->maxbounds.metrics.descent = MINSHORT;
  486.     pfi->maxbounds.metrics.characterWidth = opf->pCI->metrics.characterWidth;
  487.  
  488.     /* For each character, set the per-character metrics, scale the glyph,
  489.      * and check per-font minbounds and maxbounds character information.
  490.      */
  491.  
  492.     /* Allocate the scratch space for the glyph scaling routine. */
  493.     if (! (scratch = (int *)
  494.     ALLOCATE_LOCAL((int) ((opfi->maxbounds.metrics.rightSideBearing -
  495.                opfi->minbounds.metrics.leftSideBearing)
  496.               * widthMult * sizeof(int))))) { 
  497.     xfree(fontspace);
  498.     return (FontPtr) NULL;
  499.     }
  500.  
  501.     glyphBytesOffset = 0;
  502.     pci = pf->pCI;
  503.     for (opci = opf->pCI;  nchars;  pci++, opci++, --nchars) {
  504.     int        width, height;
  505.  
  506.     if (! (pci->exists = opci->exists))
  507.         continue;
  508.  
  509.     /* Determine current and new width and height */
  510.  
  511.     width = GLYPHWIDTHPIXELS(opci);
  512.     height = GLYPHHEIGHTPIXELS(opci);
  513.     newWidth = width * widthMult;
  514.     newHeight = height * heightMult;
  515.  
  516.     /* Scale the glyph */
  517.  
  518.     ScaleBitmap(&(opf->pGlyphs[(int) opci->byteOffset]), width,
  519.             height, &(pf->pGlyphs[(int) glyphBytesOffset]), newWidth,
  520.             newHeight, scratch);
  521.  
  522.     pci->byteOffset = glyphBytesOffset;
  523.     glyphBytesOffset += (PADGLYPHWIDTHBYTES(newWidth) * newHeight);
  524.  
  525.     /* Scale the character metrics */
  526.  
  527.     pci->metrics.leftSideBearing = (opci->metrics.leftSideBearing *
  528.                     widthMult);
  529.     pci->metrics.rightSideBearing = newWidth +
  530.         pci->metrics.leftSideBearing;
  531.     pci->metrics.ascent = opci->metrics.ascent * heightMult;
  532.     pci->metrics.descent = newHeight - pci->metrics.ascent;
  533.     pci->metrics.characterWidth = opci->metrics.characterWidth * widthMult;
  534.     pci->metrics.attributes = opci->metrics.attributes;
  535.  
  536. #define MINMAX(field) \
  537.     if (pfi->minbounds.metrics.field > pci->metrics.field) \
  538.         pfi->minbounds.metrics.field = pci->metrics.field; \
  539.     if (pfi->maxbounds.metrics.field < pci->metrics.field) \
  540.         pfi->maxbounds.metrics.field = pci->metrics.field
  541.  
  542.         MINMAX(leftSideBearing);
  543.     MINMAX(rightSideBearing);
  544.     MINMAX(ascent);
  545.     MINMAX(descent);
  546.     MINMAX(characterWidth);
  547. #undef MINMAX
  548.  
  549.     }
  550.     pci = pf->pCI;
  551.     DEALLOCATE_LOCAL((char *) scratch);
  552.  
  553.     /* Check and set ink metrics */
  554.     if (pfi->inkMetrics) {
  555.     CharInfoPtr pci;
  556.     int n;
  557.     n = (bytestoalloc - bytestoink) / sizeof(CharInfoRec);
  558.     bcopy(opf->pInkMin, pf->pInkMin, n);
  559.     for (pci=pf->pInkMin; n; n--, pci++) {
  560.         if (pci->exists) {
  561.         pci->metrics.leftSideBearing *= widthMult;
  562.         pci->metrics.rightSideBearing *= widthMult;
  563.         pci->metrics.ascent *= heightMult;
  564.         pci->metrics.descent *= heightMult;
  565.         pci->metrics.characterWidth *= widthMult;
  566.         }
  567.     }
  568.     }
  569.     return pf;
  570. }
  571.  
  572. static int lcm(a, b)        /* least common multiple */
  573.     int a, b;
  574. {
  575.     register int m;
  576.     register int larger, smaller;
  577.  
  578.     m = larger = max(a, b);
  579.     smaller =    min(a, b);
  580.     
  581.     while (m % smaller)
  582.     m += larger;
  583.     return m;
  584. }
  585.  
  586. static void ScaleBitmap(bitmap, width, height,
  587.          newBitmap, newWidth, newHeight, scratch)
  588.     char *    bitmap;        /* padded bitmap to be scaled */
  589.     int        width;        /* unpadded width of bitmap in bits */
  590.     int        height;        /* unpadded height of bitmap in bits */
  591.     char *    newBitmap;    /* allocated, zero'ed, padded memory */
  592.     int        newWidth;    /* unpadded width of new bitmap in bits */
  593.     int        newHeight;    /* unpadded height of new bitmap in bits */
  594.     int *    scratch;    /* scratch memory: newWidth * sizeof int */
  595. {
  596.     int        kcounter;    /* 0 <= kcounter <= k */
  597.     int        lcounter;    /* 0 <= lcounter <= l */
  598.     int        kkcounter;    /* 0 <= kkcounter <= kk */
  599.     int        llcounter;    /* 0 <= llcounter <= ll */
  600.     int        newBit;        /* newBitmap column index, by bits */
  601.     int    *    acc;        /* pseudonym for scratch */
  602.     int        bitValue;    /* tmp variable */
  603.     int        dataByte;
  604.     char *    dataBytePointer;
  605.     char *    saveDataBytePointer;
  606.  
  607.     /* The following variables have constant values, once assigned. */
  608.  
  609.     int        virtualWidth;    /* unpadded bit width of the virtual bitmap */
  610.     int        virtualHeight;    /* unpadded bit height of the virtual bitmap */
  611.     int        k;        /* horizontal bit copies in virtualBitmap */
  612.     int        l;        /* vertical bit copies in virtualBitmap */
  613.     int        kk;         /* horiz. virtual bits in a newBitmap bit */
  614.     int        ll;         /* vertical virtual bits in a newBitmap bit */
  615.     int        threshold;
  616.     int        padWidth;    /* actual width in bytes of pad in bitmap */
  617.     int        newPadWidth;
  618.  
  619.     if (!newWidth || !newHeight)
  620.     return;
  621.  
  622.     padWidth = PADGLYPHWIDTHBYTES(width) - ((width + 7) >> 3);
  623.     newPadWidth = PADGLYPHWIDTHBYTES(newWidth) - ((newWidth + 7) >> 3);
  624.     virtualWidth = lcm(width, newWidth);
  625.     virtualHeight = lcm(height, newHeight);
  626.     k = virtualWidth / width;
  627.     l = virtualHeight / height;
  628.     kk = virtualWidth / newWidth;
  629.     ll = virtualHeight / newHeight;
  630.     threshold = kk * ll;
  631.  
  632.     saveDataBytePointer = bitmap;
  633.     newBitmap--;
  634.     lcounter = l;
  635.     for (; newHeight; newHeight--, newBitmap += newPadWidth) {
  636.  
  637.     newBit = newWidth;
  638.     acc = scratch;
  639.     do 
  640.         *acc++ = threshold;
  641.     while (--newBit);
  642.  
  643.     llcounter = ll;
  644.     while (llcounter) {
  645.         int        bit;    /* index into glyph row, indicating a bit */
  646.         int        row_dup;    /* row duplication count from source */
  647.         int        kdup;
  648.         int        kkdup;
  649.         
  650.         if (! lcounter) {
  651.         lcounter = l;
  652.         dataBytePointer += padWidth;
  653.         saveDataBytePointer = dataBytePointer;
  654.         } else 
  655.         dataBytePointer = saveDataBytePointer;
  656.  
  657.         if ((row_dup = llcounter) > lcounter)
  658.         row_dup = lcounter;
  659.         lcounter -= row_dup;
  660.         llcounter -= row_dup;
  661.         row_dup <<= 1;
  662.  
  663.         bit = 1;
  664.         kdup = k * row_dup;
  665.         kkdup = kk * row_dup;
  666.         kcounter = 0;
  667.         newBit = newWidth;
  668.         acc = scratch;
  669.         do {
  670.         int tmp = 0;
  671.         kkcounter = kkdup;
  672.         if (! kcounter) {
  673.             /* advance to the next column of the source bitmap */
  674.             kcounter = kdup;
  675.             if (! (--bit)) {
  676.             bit = 8;
  677.             dataByte = *dataBytePointer++;
  678.             }
  679.             /* extract the appropriate bit from source bitmap */
  680. #if (BITMAP_BIT_ORDER == LSBFirst)
  681.             bitValue = dataByte & 1;
  682.             dataByte >>= 1;
  683. #else
  684.             bitValue = dataByte & 128;
  685.             dataByte <<= 1;
  686. #endif
  687.         }
  688.         while ((kkcounter -= kcounter) > 0) {
  689.             if (bitValue)
  690.             tmp += kcounter;
  691.             /* advance to the next column of the source bitmap */
  692.             kcounter = kdup;
  693.             if (! (--bit)) {
  694.             bit = 8;
  695.             dataByte = *dataBytePointer++;
  696.             }
  697.             /* extract the appropriate bit from source bitmap */
  698. #if (BITMAP_BIT_ORDER == LSBFirst)
  699.             bitValue = dataByte & 1;
  700.             dataByte >>= 1;
  701. #else
  702.             bitValue = dataByte & 128;
  703.             dataByte <<= 1;
  704. #endif
  705.         }
  706.         if (bitValue)
  707.             tmp += kcounter + kkcounter;
  708.         kcounter = -kkcounter;
  709.         *acc++ -= tmp;
  710.         }
  711.         while (--newBit);
  712.     }
  713.     /* Set the appropriate bits in newBitmap, based on the count of bits
  714.      * set in the virtual bitmap which map to a single bit in the new
  715.      * bitmap, and based on the knowing the constant number of bits in
  716.      * the virtual bitmap which map to a bit in the new bitmap.
  717.      */
  718.     acc=scratch;
  719.  
  720. #if (BITMAP_BIT_ORDER == LSBFirst)
  721.     bitValue=128;
  722. #else
  723.     bitValue=1;
  724. #endif
  725.     newBit = newWidth;
  726.     do {
  727. #if (BITMAP_BIT_ORDER == LSBFirst)
  728.         if ((bitValue <<= 1) == 256) {
  729.         bitValue = 0x1;
  730.         newBitmap++;
  731.         }
  732. #else
  733.         if (! (bitValue >>= 1)) {
  734.         bitValue = 128;
  735.         newBitmap++;
  736.         }
  737. #endif
  738.         if (*acc++ < 0)
  739.         *newBitmap |= bitValue;
  740.     } while (--newBit);
  741.     }
  742. }
  743.  
  744. /*
  745.  *    exported interfaces
  746.  */
  747.  
  748. FontFile
  749. FindScaledFont(path, fontname, table)
  750.     FontPathPtr path;
  751.     char *fontname;
  752.     FontTable *table;
  753. {
  754. #if (BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER)
  755.     return NullFontFile; /* XXX we don't deal with this case yet */
  756. #else
  757.     char fname[MAXFNAMELEN];
  758.     FontFile ff;
  759.     Scalables vals;
  760.     register int i;
  761.     Bool found;
  762.     Scalables best;
  763.     FontPtr font = NullFont;
  764.     FontPtr scaled_font;
  765.     double dx, dy;
  766.     FontTable tmptab;
  767.     DIXFontProp *tmpProps;
  768.     int    propCount;
  769.     char canonname[1024];
  770.     char scalename[1024];
  771.  
  772.     *table = scaledFonts;
  773.     /* first see if we already have it */
  774.     i = FindNameInFontTable(scaledFonts, fontname, &found);
  775.     if (found) {
  776.     ff = &scaledFonts->file.ff[scaledFonts->name.fn[i].u.index];
  777.     if (ff->private)
  778.         return ff;
  779.     }
  780.     strcpy(fname, fontname);
  781.     /* make sure it is a valid XLFD name, and get canonical form */
  782.     if (!ParseXLFDName(fname, &vals, '0') ||
  783.     !vals.pixel || !vals.point || !vals.x || !vals.y || !vals.width ||
  784.     ((vals.pixel < 0) && (vals.point < 0)))
  785.     return NullFontFile;
  786.     if ((vals.point > 0) && (vals.y > 0))
  787.     {
  788.     best.pixel = (vals.point * vals.y * 10) / 7227;
  789.     if (vals.pixel < 0)
  790.         vals.pixel = best.pixel;
  791.     else if ((best.pixel < vals.pixel - 1) ||
  792.          (best.pixel > vals.pixel + 1))
  793.         return NullFontFile;
  794.     }
  795.     else if (vals.pixel > 0)
  796.     {
  797.     if (vals.point > 0)
  798.         vals.y = (vals.pixel * 7227) / (vals.point * 10);
  799.     else if (vals.y > 0)
  800.         vals.point = (vals.pixel * 7227) / (vals.y * 10);
  801.     }
  802.     if (vals.x < 0)
  803.     vals.x = vals.y;
  804.     if (found) {
  805.     /* get values of font to scale */
  806.     if (!ParseXLFDName(ff->name, &best, '\0'))
  807.         return NullFontFile;
  808.     strcpy(canonname, scaledFonts->name.fn[i].name);
  809.     } else {
  810.     /* make sure the canonical form exists */
  811.     FontPathPtr fpr;
  812.  
  813.     fpr = ExpandFontNamePattern((unsigned)strlen(fname), fname, 1);
  814.     if (!fpr)
  815.         return NullFontFile;
  816.     if (!fpr->npaths)
  817.     {
  818.         FreeFontRecord(fpr);
  819.         return NullFontFile;
  820.     }
  821.     strcpy(canonname, fpr->paths[0]);
  822.     FreeFontRecord(fpr);
  823.     ff = FindFontFile (path, canonname, 0, FALSE, &tmptab);
  824.     if (!ff || !ff->alias)
  825.         return NullFontFile;
  826.     strcpy(fname, ff->name);
  827.     /* get the wildcard form */
  828.     if (!ParseXLFDName(fname, &best, '*'))
  829.         return NullFontFile;
  830.     }
  831.     if (vals.y < 0)
  832.     {
  833.     if (best.y <= 0)
  834.         return NullFontFile;
  835.     vals.y = best.y;
  836.     if (vals.point < 0)
  837.         vals.point = (vals.pixel * 7227) / (vals.y * 10);
  838.     else
  839.         vals.pixel = (vals.point * vals.y * 10) / 7227;
  840.     if (vals.x < 0)
  841.         vals.x = vals.y;
  842.     }
  843.     if (found)
  844.     font = FontFileLoad(ff->name, (unsigned)strlen(ff->name));
  845.     else if (FindBestToScale(fname, &vals, &best))
  846.     font = FontFileLoad(fname, (unsigned)strlen(fname));
  847.     if (!font)
  848.     return NullFontFile;
  849.     ComputeScaleFactors(&best, &vals, &dx, &dy);
  850.     if (vals.width < 0)
  851.     vals.width = best.width * dx;
  852.     /* prepare font properties for the new font */
  853.     tmpProps = (DIXFontProp *) 
  854.     ALLOCATE_LOCAL(sizeof(DIXFontProp) *
  855.                (sizeof(fontNamePropTable) / sizeof(fontProp) +
  856.             sizeof(fontPropTable) / sizeof(fontProp)));
  857.     if (!tmpProps)
  858.     return (FontFile) NULL;
  859.     propCount = ComputeScaledProperties(font, canonname, &vals, dx, dy,
  860.                     scalename, tmpProps);
  861.     /* compute the scaled font */
  862.     scaled_font = ScaleFont(font, dx, dy, tmpProps, propCount);
  863.     DEALLOCATE_LOCAL(tmpProps);
  864.     /* do not need the base font any more */
  865.     if (!font->refcnt)
  866.     FontUnload(font);
  867.     if (!scaled_font)
  868.     return NullFontFile;
  869.     /* enter into the table if new */
  870.     if (!found) {
  871.     i = AddFileEntry(scaledFonts, fname, True);
  872.     if (i >= 0) {
  873.         ff = &scaledFonts->file.ff[i];
  874.         i = AddVerifiedNameEntry(scaledFonts, scalename, i);
  875.     }
  876.     if (i <= 0) {
  877.         FontUnload(scaled_font);
  878.         return NullFontFile;
  879.     }
  880.     }
  881.     ff->private = (Opaque) scaled_font;
  882.     scaled_font->osPrivate = (pointer) ff;
  883.     return ff;
  884. #endif
  885. }
  886.  
  887. void
  888. FreeScaledFonts()
  889. {
  890.     register FontTable table = scaledFonts;
  891.     register int i;
  892.     register FontPtr font;
  893.  
  894.     if (table) {
  895.     for (i = 0; i < table->file.used; i++) {
  896.         if (font = (FontPtr) table->file.ff[i].private)
  897.         font->osPrivate = NULL;
  898.     }
  899.     FreeFontTable(table);
  900.     }
  901.     scaledFonts = MakeFontTable("", 10);
  902. }
  903.  
  904.