3 Copyright 1991, 1994, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
30 * Author: Keith Packard, MIT X Consortium
38 * Translate monolithic #defines to modular definitions
42 #define XFONT_PCFFORMAT 1
46 #define XFONT_SNFFORMAT 1
50 #define XFONT_BDFFORMAT 1
53 #include <X11/fonts/fntfilst.h>
54 #include <X11/fonts/bitmap.h>
55 #include <X11/fonts/fontutil.h>
59 #define MAX(a,b) (((a)>(b)) ? a : b)
62 /* Should get this from elsewhere */
63 extern unsigned long serverGeneration;
65 static void bitmapUnloadScalable (FontPtr pFont);
66 static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci,
67 CharInfoPtr pci, double *inv_xform,
68 double widthMult, double heightMult );
69 static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf,
70 double widthMult, double heightMult,
71 FontScalablePtr vals);
74 atom, truncate_atom, pixel_size, point_size, resolution_x,
75 resolution_y, average_width, scaledX, scaledY, unscaled, fontname,
76 raw_ascent, raw_descent, raw_pixelsize, raw_pointsize,
77 raw_average_width, uncomputed
80 typedef struct _fontProp {
86 static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe,
90 double *dxp, double *dyp,
91 double *sdxp, double *sdyp,
92 FontPathElementPtr *fpep );
94 static unsigned long bitscaleGeneration = 0; /* initialization flag */
96 static fontProp fontNamePropTable[] = {
97 { "FOUNDRY", 0, atom },
98 { "FAMILY_NAME", 0, atom },
99 { "WEIGHT_NAME", 0, atom },
100 { "SLANT", 0, atom },
101 { "SETWIDTH_NAME", 0, atom },
102 { "ADD_STYLE_NAME", 0, atom },
103 { "PIXEL_SIZE", 0, pixel_size },
104 { "POINT_SIZE", 0, point_size },
105 { "RESOLUTION_X", 0, resolution_x },
106 { "RESOLUTION_Y", 0, resolution_y },
107 { "SPACING", 0, atom },
108 { "AVERAGE_WIDTH", 0, average_width },
109 { "CHARSET_REGISTRY", 0, atom },
110 { "CHARSET_ENCODING", 0, truncate_atom },
111 { "FONT", 0, fontname },
112 { "RAW_ASCENT", 0, raw_ascent },
113 { "RAW_DESCENT", 0, raw_descent },
114 { "RAW_PIXEL_SIZE", 0, raw_pixelsize },
115 { "RAW_POINT_SIZE", 0, raw_pointsize },
116 { "RAW_AVERAGE_WIDTH", 0, raw_average_width }
119 #define TRANSFORM_POINT(matrix, x, y, dest) \
120 ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
121 (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
123 #define CHECK_EXTENT(lsb, rsb, desc, asc, data) \
124 ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
125 (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
126 (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
127 (asc) < (data)[1] ? (asc) = (data)[1] : 0)
129 #define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp))
131 /* Warning: order of the next two tables is critically interdependent.
132 Location of "unscaled" properties at the end of fontPropTable[]
135 static fontProp fontPropTable[] = {
136 { "MIN_SPACE", 0, scaledX },
137 { "NORM_SPACE", 0, scaledX },
138 { "MAX_SPACE", 0, scaledX },
139 { "END_SPACE", 0, scaledX },
140 { "AVG_CAPITAL_WIDTH", 0, scaledX },
141 { "AVG_LOWERCASE_WIDTH", 0, scaledX },
142 { "QUAD_WIDTH", 0, scaledX },
143 { "FIGURE_WIDTH", 0, scaledX },
144 { "SUPERSCRIPT_X", 0, scaledX },
145 { "SUPERSCRIPT_Y", 0, scaledY },
146 { "SUBSCRIPT_X", 0, scaledX },
147 { "SUBSCRIPT_Y", 0, scaledY },
148 { "SUPERSCRIPT_SIZE", 0, scaledY },
149 { "SUBSCRIPT_SIZE", 0, scaledY },
150 { "SMALL_CAP_SIZE", 0, scaledY },
151 { "UNDERLINE_POSITION", 0, scaledY },
152 { "UNDERLINE_THICKNESS", 0, scaledY },
153 { "STRIKEOUT_ASCENT", 0, scaledY },
154 { "STRIKEOUT_DESCENT", 0, scaledY },
155 { "CAP_HEIGHT", 0, scaledY },
156 { "X_HEIGHT", 0, scaledY },
157 { "ITALIC_ANGLE", 0, unscaled },
158 { "RELATIVE_SETWIDTH", 0, unscaled },
159 { "RELATIVE_WEIGHT", 0, unscaled },
160 { "WEIGHT", 0, unscaled },
161 { "DESTINATION", 0, unscaled },
162 { "PCL_FONT_NAME", 0, unscaled },
163 { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled }
166 static fontProp rawFontPropTable[] = {
167 { "RAW_MIN_SPACE", 0, },
168 { "RAW_NORM_SPACE", 0, },
169 { "RAW_MAX_SPACE", 0, },
170 { "RAW_END_SPACE", 0, },
171 { "RAW_AVG_CAPITAL_WIDTH", 0, },
172 { "RAW_AVG_LOWERCASE_WIDTH", 0, },
173 { "RAW_QUAD_WIDTH", 0, },
174 { "RAW_FIGURE_WIDTH", 0, },
175 { "RAW_SUPERSCRIPT_X", 0, },
176 { "RAW_SUPERSCRIPT_Y", 0, },
177 { "RAW_SUBSCRIPT_X", 0, },
178 { "RAW_SUBSCRIPT_Y", 0, },
179 { "RAW_SUPERSCRIPT_SIZE", 0, },
180 { "RAW_SUBSCRIPT_SIZE", 0, },
181 { "RAW_SMALL_CAP_SIZE", 0, },
182 { "RAW_UNDERLINE_POSITION", 0, },
183 { "RAW_UNDERLINE_THICKNESS", 0, },
184 { "RAW_STRIKEOUT_ASCENT", 0, },
185 { "RAW_STRIKEOUT_DESCENT", 0, },
186 { "RAW_CAP_HEIGHT", 0, },
187 { "RAW_X_HEIGHT", 0, }
191 initFontPropTable(void)
196 i = sizeof(fontNamePropTable) / sizeof(fontProp);
197 for (t = fontNamePropTable; i; i--, t++)
198 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
200 i = sizeof(fontPropTable) / sizeof(fontProp);
201 for (t = fontPropTable; i; i--, t++)
202 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
204 i = sizeof(rawFontPropTable) / sizeof(fontProp);
205 for (t = rawFontPropTable; i; i--, t++)
206 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
211 GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name)
213 FontDirectoryPtr dir;
215 dir = (FontDirectoryPtr) fpe->private;
216 return FontFileFindNameInDir (&dir->scalable, name);
221 get_matrix_horizontal_component(double *matrix)
223 return hypot(matrix[0], matrix[1]);
227 get_matrix_vertical_component(double *matrix)
229 return hypot(matrix[2], matrix[3]);
234 ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to,
235 double *dx, double *dy, double *sdx, double *sdy,
238 double srcpixelset, destpixelset, srcpixel, destpixel;
240 srcpixelset = get_matrix_horizontal_component(from->pixel_matrix);
241 destpixelset = get_matrix_horizontal_component(to->pixel_matrix);
242 srcpixel = get_matrix_vertical_component(from->pixel_matrix);
243 destpixel = get_matrix_vertical_component(to->pixel_matrix);
245 if (srcpixelset >= EPS)
247 *dx = destpixelset / srcpixelset;
248 *sdx = 1000.0 / srcpixelset;
255 /* If client specified a width, it overrides setsize; in this
256 context, we interpret width as applying to the font before any
257 rotation, even though that's not what is ultimately returned in
259 if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS)
261 double rescale = (double)to->width / (double)from->width;
263 /* If the client specified a transformation matrix, the rescaling
264 for width does *not* override the setsize. Instead, just check
265 for consistency between the setsize from the matrix and the
266 setsize that would result from rescaling according to the width.
267 This assumes (perhaps naively) that the width is correctly
268 reported in the name. As an interesting side effect, this test
269 may result in choosing a different source bitmap (one that
270 scales consistently between the setsize *and* the width) than it
271 would choose if a width were not specified. Sort of a hidden
272 multiple-master functionality. */
273 if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
274 (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
276 /* Reject if resulting width difference is >= 1 pixel */
277 if (fabs(rescale * from->width - *dx * from->width) >= 10)
282 *rescale_x = rescale/(*dx);
289 *dy = destpixel / srcpixel;
290 *sdy = 1000.0 / srcpixel;
298 /* favor enlargement over reduction because of aliasing resulting
307 score += (int)(((double)(3 * s)) / m); \
309 score += (int)(((double)(2 * s)) * m); \
312 /* don't need to favor enlargement when looking for bitmap that can
313 be used unscalable */
314 #define SCORE2(m,s) \
316 score += (int)(((double)(8 * s)) / m); \
318 score += (int)(((double)(8 * s)) * m);
321 FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry,
322 FontScalablePtr vals, FontScalablePtr best,
323 double *dxp, double *dyp,
324 double *sdxp, double *sdyp,
325 FontPathElementPtr *fpep)
327 FontScalableRec temp;
329 int best_score, best_unscaled_score,
331 double dx = 0.0, sdx = 0.0, dx_amount = 0.0,
332 dy = 0.0, sdy = 0.0, dy_amount = 0.0,
333 best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0,
334 best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0,
335 best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0,
336 rescale_x = 0.0, best_rescale_x = 0.0,
337 best_unscaled_rescale_x = 0.0;
339 FontNameRec zeroName;
340 char zeroChars[MAXFONTNAMELEN];
341 FontDirectoryPtr dir;
342 FontScaledPtr scaled;
343 FontScalableExtraPtr extra;
344 FontScaledPtr best_scaled, best_unscaled;
345 FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL;
346 FontEntryPtr bitmap = NULL;
349 FontPathElementPtr bitmap_fpe = NULL;
350 FontNameRec xlfdName;
352 /* find the best match */
357 best_unscaled_score = -1;
358 best_dx_amount = best_dy_amount = HUGE_VAL;
359 memcpy (zeroChars, entry->name.name, entry->name.length);
360 zeroChars[entry->name.length] = '\0';
361 zeroName.name = zeroChars;
362 FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO);
363 zeroName.length = strlen (zeroChars);
364 zeroName.ndashes = entry->name.ndashes;
365 xlfdName.name = vals->xlfdName;
366 xlfdName.length = strlen(xlfdName.name);
367 xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length);
368 restart_bestscale_loop: ;
370 * Look through all the registered bitmap sources for
371 * the same zero name as ours; entries along that one
372 * can be scaled as desired.
374 for (source = 0; source < FontFileBitmapSources.count; source++)
376 /* There might already be a bitmap that satisfies the request
377 but didn't have a zero name that was found by the scalable
378 font matching logic. Keep track if there is. */
379 if (bitmap == NULL && vals->xlfdName != NULL)
381 bitmap_fpe = FontFileBitmapSources.fpe[source];
382 dir = (FontDirectoryPtr) bitmap_fpe->private;
383 bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName);
384 if (bitmap && bitmap->type != FONT_ENTRY_BITMAP)
386 if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0)
389 xlfdName.name = bitmap->u.alias.resolved;
390 xlfdName.length = strlen(xlfdName.name);
391 xlfdName.ndashes = FontFileCountDashes(xlfdName.name,
394 goto restart_bestscale_loop;
401 if (FontFileBitmapSources.fpe[source] == fpe)
405 dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
406 zero = FontFileFindNameInDir (&dir->scalable, &zeroName);
410 extra = zero->u.scalable.extra;
411 for (i = 0; i < extra->numScaled; i++)
413 scaled = &extra->scaled[i];
416 if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy,
422 SCORE(dy_amount, 10);
424 if ((score > best_score) ||
425 ((score == best_score) &&
426 ((dy_amount < best_dy_amount) ||
427 ((dy_amount == best_dy_amount) &&
428 (dx_amount < best_dx_amount)))))
430 best_fpe = FontFileBitmapSources.fpe[source];
431 best_scaled = scaled;
437 best_dx_amount = dx_amount;
438 best_dy_amount = dy_amount;
439 best_rescale_x = rescale_x;
441 /* Is this font a candidate for use without ugly rescaling? */
442 if (fabs(dx) > EPS && fabs(dy) > EPS &&
443 fabs(vals->pixel_matrix[0] * rescale_x -
444 scaled->vals.pixel_matrix[0]) < 1 &&
445 fabs(vals->pixel_matrix[1] * rescale_x -
446 scaled->vals.pixel_matrix[1]) < EPS &&
447 fabs(vals->pixel_matrix[2] -
448 scaled->vals.pixel_matrix[2]) < EPS &&
449 fabs(vals->pixel_matrix[3] -
450 scaled->vals.pixel_matrix[3]) < 1)
452 /* Yes. The pixel sizes are close on the diagonal and
453 extremely close off the diagonal. */
455 SCORE2(vals->pixel_matrix[3] /
456 scaled->vals.pixel_matrix[3], 10);
457 SCORE2(vals->pixel_matrix[0] * rescale_x /
458 scaled->vals.pixel_matrix[0], 1);
459 if (score > best_unscaled_score)
461 best_unscaled_fpe = FontFileBitmapSources.fpe[source];
462 best_unscaled = scaled;
463 best_unscaled_sdx = sdx / dx;
464 best_unscaled_sdy = sdy / dy;
465 best_unscaled_score = score;
466 best_unscaled_rescale_x = rescale_x;
473 *best = best_unscaled->vals;
474 *fpep = best_unscaled_fpe;
477 *sdxp = best_unscaled_sdx;
478 *sdyp = best_unscaled_sdy;
479 rescale_x = best_unscaled_rescale_x;
480 result = best_unscaled->bitmap;
482 else if (best_scaled)
484 *best = best_scaled->vals;
490 rescale_x = best_rescale_x;
491 result = best_scaled->bitmap;
496 if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0))
499 FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE);
500 if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x))
506 if (result && rescale_x != 1.0)
508 /* We have rescaled horizontally due to an XLFD width field. Change
509 the matrix appropriately */
510 vals->pixel_matrix[0] *= rescale_x;
511 vals->pixel_matrix[1] *= rescale_x;
512 vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK;
513 /* Recompute and reround the FontScalablePtr values after
514 rescaling for the new width. */
515 FontFileCompleteXLFD(vals, vals);
524 return (x >= 0) ? (long)(x + .5) : (long)(x - .5);
528 computeProps(FontPropPtr pf, char *wasStringProp,
529 FontPropPtr npf, char *isStringProp,
530 unsigned int nprops, double xfactor, double yfactor,
531 double sXfactor, double sYfactor)
536 double rawfactor = 0.0;
538 for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) {
539 n = sizeof(fontPropTable) / sizeof(fontProp);
540 for (t = fontPropTable; n && (t->atom != pf->name); n--, t++);
546 npf->value = doround(xfactor * (double)pf->value);
547 rawfactor = sXfactor;
550 npf->value = doround(yfactor * (double)pf->value);
551 rawfactor = sYfactor;
554 npf->value = pf->value;
555 npf->name = pf->name;
558 *isStringProp++ = *wasStringProp;
563 if (t->type != unscaled)
565 npf->name = pf->name;
568 npf->value = doround(rawfactor * (double)pf->value);
569 npf->name = rawFontPropTable[t - fontPropTable].atom;
572 *isStringProp++ = *wasStringProp;
573 *isStringProp++ = *wasStringProp;
581 ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */
582 char *name, /* name of resulting font */
583 FontScalablePtr vals,
584 double dx, double dy, /* scale factors in x and y */
585 double sdx, double sdy, /* directions */
586 long sWidth, /* 1000-pixel average width */
587 FontPropPtr *pProps, /* returns properties;
589 char **pIsStringProp) /* return booleans;
593 char *ptr1 = NULL, *ptr2 = NULL;
600 if (bitscaleGeneration != serverGeneration) {
602 bitscaleGeneration = serverGeneration;
604 nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) +
605 sizeof(rawFontPropTable) / sizeof(fontProp);
606 fp = malloc(sizeof(FontPropRec) * nProps);
609 fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n",
610 (unsigned long)sizeof(FontPropRec), nProps);
613 isStringProp = malloc (nProps);
614 *pIsStringProp = isStringProp;
617 fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps);
622 for (fpt = fontNamePropTable, n = NPROPS;
624 fp++, fpt++, n--, isStringProp++)
630 if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0');
636 fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE);
640 for (ptr3 = ptr1; *ptr3; ptr3++)
643 if (!*ptr3) ptr3 = ptr2;
644 fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE);
648 fp->value = doround(vals->pixel_matrix[3]);
651 fp->value = doround(vals->point_matrix[3] * 10.0);
660 fp->value = vals->width;
663 fp->value = MakeAtom(name, strlen(name), TRUE);
667 fp->value = sourceFontInfo->fontAscent * sdy;
670 fp->value = sourceFontInfo->fontDescent * sdy;
673 fp->value = (long)(72270.0 / (double)vals->y + .5);
678 case raw_average_width:
684 fp->name = fpt->atom;
687 n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
688 fp, isStringProp, sourceFontInfo->nprops, dx, dy,
695 compute_xform_matrix(FontScalablePtr vals, double dx, double dy,
696 double *xform, double *inv_xform,
697 double *xmult, double *ymult)
700 double pixel = get_matrix_vertical_component(vals->pixel_matrix);
701 double pixelset = get_matrix_horizontal_component(vals->pixel_matrix);
703 if (pixel < EPS || pixelset < EPS) return 0;
705 /* Initialize the transformation matrix to the scaling factors */
706 xform[0] = dx / pixelset;
707 xform[1] = xform[2] = 0.0;
708 xform[3] = dy / pixel;
710 /* Inline matrix multiply -- somewhat ugly to minimize register usage */
711 #define MULTIPLY_XFORM(a,b,c,d) \
713 register double aa = (a), bb = (b), cc = (c), dd = (d); \
714 register double temp; \
715 temp = aa * xform[0] + cc * xform[1]; \
716 aa = aa * xform[2] + cc * xform[3]; \
717 xform[1] = bb * xform[0] + dd * xform[1]; \
718 xform[3] = bb * xform[2] + dd * xform[3]; \
723 /* Rescale the transformation matrix for size of source font */
724 MULTIPLY_XFORM(vals->pixel_matrix[0],
725 vals->pixel_matrix[1],
726 vals->pixel_matrix[2],
727 vals->pixel_matrix[3]);
733 if (inv_xform == NULL) return 1;
735 /* Compute the determinant for use in inverting the matrix. */
736 det = xform[0] * xform[3] - xform[1] * xform[2];
738 /* If the determinant is tiny or zero, give up */
739 if (fabs(det) < EPS) return 0;
741 /* Compute the inverse */
742 inv_xform[0] = xform[3] / det;
743 inv_xform[1] = -xform[1] / det;
744 inv_xform[2] = -xform[2] / det;
745 inv_xform[3] = xform[0] / det;
752 * returns a pointer to the new scaled font, or NULL (due to AllocError).
755 ScaleFont(FontPtr opf, /* originating font */
756 double widthMult, /* glyphs width scale factor */
757 double heightMult, /* glyphs height scale factor */
758 double sWidthMult, /* scalable glyphs width scale factor */
759 double sHeightMult, /* scalable glyphs height scale factor */
760 FontScalablePtr vals,
761 double *newWidthMult, /* return: X component of glyphs width
763 double *newHeightMult, /* return: Y component of glyphs height
765 long *sWidth) /* return: average 1000-pixel width */
770 BitmapFontPtr bitmapFont,
774 int nchars = 0; /* how many characters in the font */
776 int firstCol, lastCol, firstRow, lastRow;
777 double xform[4], inv_xform[4];
779 int totalwidth = 0, totalchars = 0;
780 #define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \
781 firstRow - opf->info.firstRow) * \
782 (opf->info.lastCol - opf->info.firstCol + 1) + \
783 (i)%(lastCol - firstCol + 1) + \
784 firstCol - opf->info.firstCol)
789 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
792 if (!(pf = CreateFontRec())) {
793 fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n",
794 (unsigned long)sizeof(FontRec));
799 pf->byte = opf->byte;
800 pf->glyph = opf->glyph;
801 pf->scan = opf->scan;
803 pf->get_glyphs = bitmapGetGlyphs;
804 pf->get_metrics = bitmapGetMetrics;
805 pf->unload_font = bitmapUnloadScalable;
806 pf->unload_glyphs = NULL;
810 /* If charset subsetting specified in vals, determine what our range
811 needs to be for the output font */
822 for (i = 0; i < vals->nranges; i++)
824 if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high)
826 firstCol = opfi->firstCol;
827 lastCol = opfi->lastCol;
829 if (firstCol > vals->ranges[i].min_char_low)
830 firstCol = vals->ranges[i].min_char_low;
831 if (lastCol < vals->ranges[i].max_char_low)
832 lastCol = vals->ranges[i].max_char_low;
833 if (firstRow > vals->ranges[i].min_char_high)
834 firstRow = vals->ranges[i].min_char_high;
835 if (lastRow < vals->ranges[i].max_char_high)
836 lastRow = vals->ranges[i].max_char_high;
839 if (firstCol > lastCol || firstRow > lastRow)
842 if (firstCol < opfi->firstCol)
843 firstCol = opfi->firstCol;
844 if (lastCol > opfi->lastCol)
845 lastCol = opfi->lastCol;
846 if (firstRow < opfi->firstRow)
847 firstRow = opfi->firstRow;
848 if (lastRow > opfi->lastRow)
849 lastRow = opfi->lastRow;
853 firstCol = opfi->firstCol;
854 lastCol = opfi->lastCol;
855 firstRow = opfi->firstRow;
856 lastRow = opfi->lastRow;
859 bitmapFont = malloc(sizeof(BitmapFontRec));
861 fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n",
862 (unsigned long)sizeof(BitmapFontRec));
865 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
866 pfi->firstRow = firstRow;
867 pfi->lastRow = lastRow;
868 pfi->firstCol = firstCol;
869 pfi->lastCol = lastCol;
870 pf->fontPrivate = (pointer) bitmapFont;
871 bitmapFont->version_num = obitmapFont->version_num;
872 bitmapFont->num_chars = nchars;
873 bitmapFont->num_tables = obitmapFont->num_tables;
874 bitmapFont->metrics = 0;
875 bitmapFont->ink_metrics = 0;
876 bitmapFont->bitmaps = 0;
877 bitmapFont->encoding = 0;
878 bitmapFont->bitmapExtra = 0;
879 bitmapFont->pDefault = 0;
880 bitmapFont->metrics = malloc(nchars * sizeof(CharInfoRec));
881 if (!bitmapFont->metrics) {
882 fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n",
883 nchars, (unsigned long)sizeof(CharInfoRec));
886 bitmapFont->encoding = calloc(NUM_SEGMENTS(nchars), sizeof(CharInfoPtr*));
887 if (!bitmapFont->encoding) {
888 fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n",
889 nchars, (unsigned long)sizeof(CharInfoPtr));
894 #define MAXSHORT 32767
896 #define MINSHORT -32768
898 pfi->anamorphic = FALSE;
899 if (heightMult != widthMult)
900 pfi->anamorphic = TRUE;
901 pfi->cachable = TRUE;
903 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
904 inv_xform, &xmult, &ymult))
907 pfi->fontAscent = opfi->fontAscent * ymult;
908 pfi->fontDescent = opfi->fontDescent * ymult;
910 pfi->minbounds.leftSideBearing = MAXSHORT;
911 pfi->minbounds.rightSideBearing = MAXSHORT;
912 pfi->minbounds.ascent = MAXSHORT;
913 pfi->minbounds.descent = MAXSHORT;
914 pfi->minbounds.characterWidth = MAXSHORT;
915 pfi->minbounds.attributes = MAXSHORT;
917 pfi->maxbounds.leftSideBearing = MINSHORT;
918 pfi->maxbounds.rightSideBearing = MINSHORT;
919 pfi->maxbounds.ascent = MINSHORT;
920 pfi->maxbounds.descent = MINSHORT;
921 pfi->maxbounds.characterWidth = MINSHORT;
922 pfi->maxbounds.attributes = MINSHORT;
924 /* Compute the transformation and inverse transformation matrices.
925 Can fail if the determinant is zero. */
927 pci = bitmapFont->metrics;
928 for (i = 0; i < nchars; i++)
930 if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))))
932 double newlsb, newrsb, newdesc, newasc, point[2];
934 #define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
935 #define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
939 int row = i / (lastCol - firstCol + 1) + firstRow;
940 int col = i % (lastCol - firstCol + 1) + firstCol;
941 int ch = (row << 8) + col;
943 for (j = 0; j < vals->nranges; j++)
944 if (ch >= minchar(vals->ranges[j]) &&
945 ch <= maxchar(vals->ranges[j]))
947 if (j == vals->nranges)
953 if (opci->metrics.leftSideBearing == 0 &&
954 opci->metrics.rightSideBearing == 0 &&
955 opci->metrics.ascent == 0 &&
956 opci->metrics.descent == 0 &&
957 opci->metrics.characterWidth == 0)
962 if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
963 bitmapFont->encoding[SEGMENT_MAJOR(i)]=
964 calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
965 if(!bitmapFont->encoding[SEGMENT_MAJOR(i)])
968 ACCESSENCODINGL(bitmapFont->encoding, i) = pci;
970 /* Compute new extents for this glyph */
971 TRANSFORM_POINT(xform,
972 opci->metrics.leftSideBearing,
973 -opci->metrics.descent,
979 TRANSFORM_POINT(xform,
980 opci->metrics.leftSideBearing,
981 opci->metrics.ascent,
983 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
984 TRANSFORM_POINT(xform,
985 opci->metrics.rightSideBearing,
986 -opci->metrics.descent,
988 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
989 TRANSFORM_POINT(xform,
990 opci->metrics.rightSideBearing,
991 opci->metrics.ascent,
993 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
995 pci->metrics.leftSideBearing = (int)floor(newlsb);
996 pci->metrics.rightSideBearing = (int)floor(newrsb + .5);
997 pci->metrics.descent = (int)ceil(newdesc);
998 pci->metrics.ascent = (int)floor(newasc + .5);
999 /* Accumulate total width of characters before transformation,
1000 to ascertain predominant direction of font. */
1001 totalwidth += opci->metrics.characterWidth;
1002 pci->metrics.characterWidth =
1003 doround((double)opci->metrics.characterWidth * xmult);
1004 pci->metrics.attributes =
1005 doround((double)opci->metrics.characterWidth * sWidthMult);
1006 if (!pci->metrics.characterWidth)
1008 /* Since transformation may shrink width, height, and
1009 escapement to zero, make sure existing characters
1010 are not mistaken for undefined characters. */
1012 if (pci->metrics.rightSideBearing ==
1013 pci->metrics.leftSideBearing)
1014 pci->metrics.rightSideBearing++;
1015 if (pci->metrics.ascent == -pci->metrics.descent)
1016 pci->metrics.ascent++;
1025 * For each character, set the per-character metrics, scale the glyph, and
1026 * check per-font minbounds and maxbounds character information.
1029 pci = bitmapFont->metrics;
1030 for (i = 0; i < nchars; i++)
1032 if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) &&
1033 (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))))
1036 *sWidth += abs((int)(INT16)pci->metrics.attributes);
1037 #define MINMAX(field) \
1038 if (pfi->minbounds.field > pci->metrics.field) \
1039 pfi->minbounds.field = pci->metrics.field; \
1040 if (pfi->maxbounds.field < pci->metrics.field) \
1041 pfi->maxbounds.field = pci->metrics.field
1043 MINMAX(leftSideBearing);
1044 MINMAX(rightSideBearing);
1047 MINMAX(characterWidth);
1049 /* Hack: Cast attributes into a signed quantity. Tread lightly
1050 for now and don't go changing the global Xproto.h file */
1051 if ((INT16)pfi->minbounds.attributes >
1052 (INT16)pci->metrics.attributes)
1053 pfi->minbounds.attributes = pci->metrics.attributes;
1054 if ((INT16)pfi->maxbounds.attributes <
1055 (INT16)pci->metrics.attributes)
1056 pfi->maxbounds.attributes = pci->metrics.attributes;
1060 pfi->ink_minbounds = pfi->minbounds;
1061 pfi->ink_maxbounds = pfi->maxbounds;
1064 *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars;
1067 /* Dominant direction is R->L */
1071 if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth)
1072 vals->width = pfi->minbounds.characterWidth * 10;
1074 vals->width = doround((double)*sWidth * vals->pixel_matrix[0] /
1082 FontComputeInfoAccelerators (pfi);
1084 if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) {
1089 r = pfi->defaultCh >> 8;
1090 c = pfi->defaultCh & 0xFF;
1091 if (pfi->firstRow <= r && r <= pfi->lastRow &&
1092 pfi->firstCol <= c && c <= pfi->lastCol) {
1093 cols = pfi->lastCol - pfi->firstCol + 1;
1094 r = r - pfi->firstRow;
1095 c = c - pfi->firstCol;
1096 bitmapFont->pDefault =
1097 ACCESSENCODING(bitmapFont->encoding, r * cols + c);
1101 *newWidthMult = xmult;
1102 *newHeightMult = ymult;
1108 free(bitmapFont->metrics);
1109 free(bitmapFont->ink_metrics);
1110 free(bitmapFont->bitmaps);
1111 if(bitmapFont->encoding)
1112 for(i=0; i<NUM_SEGMENTS(nchars); i++)
1113 free(bitmapFont->encoding[i]);
1114 free(bitmapFont->encoding);
1120 ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci,
1121 double *inv_xform, double widthMult, double heightMult)
1123 register char *bitmap, /* The bits */
1125 register int bpr, /* Padding information */
1127 int width, /* Extents information */
1131 register int row, /* Loop variables */
1133 INT32 deltaX, /* Increments for resampling loop */
1135 INT32 xValue, /* Subscripts for resampling loop */
1138 unsigned char *char_grayscale = 0;
1139 INT32 *diffusion_workspace = NULL, *thisrow = NULL,
1140 *nextrow = NULL, pixmult = 0;
1141 int box_x = 0, box_y = 0;
1143 static unsigned char masklsb[] =
1144 { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
1145 static unsigned char maskmsb[] =
1146 { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
1147 unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb);
1150 bitmap = opci->bits;
1151 newBitmap = pci->bits;
1152 width = GLYPHWIDTHPIXELS(opci);
1153 height = GLYPHHEIGHTPIXELS(opci);
1154 newWidth = GLYPHWIDTHPIXELS(pci);
1155 newHeight = GLYPHHEIGHTPIXELS(pci);
1156 if (!newWidth || !newHeight || !width || !height)
1159 bpr = BYTES_PER_ROW(width, pFont->glyph);
1160 newBpr = BYTES_PER_ROW(newWidth, pFont->glyph);
1162 if (widthMult > 0.0 && heightMult > 0.0 &&
1163 (widthMult < 1.0 || heightMult < 1.0))
1165 /* We are reducing in one or both dimensions. In an attempt to
1166 reduce aliasing, we'll antialias by passing the original
1167 glyph through a low-pass box filter (which results in a
1168 grayscale image), then use error diffusion to create bitonal
1169 output in the resampling loop. */
1171 /* First compute the sizes of the box filter */
1172 widthMult = ceil(1.0 / widthMult);
1173 heightMult = ceil(1.0 / heightMult);
1176 if (widthMult < (double)box_x) box_x = (int)widthMult;
1177 if (heightMult < (double)box_y) box_y = (int)heightMult;
1178 /* The pixmult value (below) is used to darken the image before
1179 we perform error diffusion: a necessary concession to the
1180 fact that it's very difficult to generate readable halftoned
1181 glyphs. The degree of darkening is proportional to the size
1182 of the blurring filter, hence inversely proportional to the
1183 darkness of the lightest gray that results from antialiasing.
1184 The result is that characters that exercise this logic (those
1185 generated by reducing from a larger source font) tend to err
1186 on the side of being too bold instead of being too light to
1188 pixmult = box_x * box_y * 192;
1190 if (box_x > 1 || box_y > 1)
1192 /* Looks like we need to anti-alias. Create a workspace to
1193 contain the grayscale character plus an additional row and
1194 column for scratch */
1195 char_grayscale = malloc((width + 1) * (height + 1));
1198 diffusion_workspace = calloc((newWidth + 2) * 2, sizeof(int));
1199 if (!diffusion_workspace)
1201 fprintf(stderr, "Warning: Couldn't allocate diffusion"
1202 " workspace (%ld)\n",
1203 (newWidth + 2) * 2 * (unsigned long)sizeof(int));
1204 free(char_grayscale);
1205 char_grayscale = (unsigned char *)0;
1207 /* Initialize our error diffusion workspace for later use */
1208 thisrow = diffusion_workspace + 1;
1209 nextrow = diffusion_workspace + newWidth + 3;
1211 fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1));
1218 /* We will be doing antialiasing. First copy the bitmap into
1219 our buffer, mapping input range [0,1] to output range
1221 register unsigned char *srcptr, *dstptr;
1222 srcptr = (unsigned char *)bitmap;
1223 dstptr = char_grayscale;
1224 for (row = 0; row < height; row++)
1226 for (col = 0; col < width; col++)
1227 *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0;
1228 srcptr += bpr; /* On to next row of source */
1229 dstptr++; /* Skip scratch column in dest */
1233 /* Our box filter has a width > 1... let's filter the rows */
1235 int right_width = box_x / 2;
1236 int left_width = box_x - right_width - 1;
1238 for (row = 0; row < height; row++)
1241 int left_size = 0, right_size = 0;
1243 srcptr = char_grayscale + (width + 1) * row;
1244 dstptr = char_grayscale + (width + 1) * height; /* scratch */
1246 /* We've computed the shape of our full box filter. Now
1247 compute the right-hand part of the moving sum */
1248 for (right_size = 0; right_size < right_width; right_size++)
1249 sum += srcptr[right_size];
1251 /* Now start moving the sum, growing the box filter, and
1252 dropping averages into our scratch buffer */
1253 for (left_size = 0; left_size < left_width; left_size++)
1255 sum += srcptr[right_width];
1256 *dstptr++ = sum / (left_size + right_width + 1);
1260 /* The box filter has reached full width... continue
1261 computation of moving average until the right side
1263 for (col = left_size; col + right_size < width; col++)
1265 sum += srcptr[right_width];
1266 *dstptr++ = sum / box_x;
1267 sum -= srcptr[-left_width];
1271 /* Collapse the right side of the box filter */
1272 for (; right_size > 0; right_size--)
1274 *dstptr++ = sum / (left_width + right_size);
1275 sum -= srcptr[-left_width];
1279 /* Done with the row... copy dest back over source */
1280 memmove(char_grayscale + (width + 1) * row,
1281 char_grayscale + (width + 1) * height,
1287 /* Our box filter has a height > 1... let's filter the columns */
1289 int bottom_height = box_y / 2;
1290 int top_height = box_y - bottom_height - 1;
1292 for (col = 0; col < width; col++)
1295 int top_size = 0, bottom_size = 0;
1297 srcptr = char_grayscale + col;
1298 dstptr = char_grayscale + width; /* scratch */
1300 /* We've computed the shape of our full box filter. Now
1301 compute the bottom part of the moving sum */
1302 for (bottom_size = 0;
1303 bottom_size < bottom_height;
1305 sum += srcptr[bottom_size * (width + 1)];
1307 /* Now start moving the sum, growing the box filter, and
1308 dropping averages into our scratch buffer */
1309 for (top_size = 0; top_size < top_height; top_size++)
1311 sum += srcptr[bottom_height * (width + 1)];
1312 *dstptr = sum / (top_size + bottom_height + 1);
1313 dstptr += width + 1;
1314 srcptr += width + 1;
1317 /* The box filter has reached full height... continue
1318 computation of moving average until the bottom
1320 for (row = top_size; row + bottom_size < height; row++)
1322 sum += srcptr[bottom_height * (width + 1)];
1323 *dstptr = sum / box_y;
1324 dstptr += width + 1;
1325 sum -= srcptr[-top_height * (width + 1)];
1326 srcptr += width + 1;
1329 /* Collapse the bottom of the box filter */
1330 for (; bottom_size > 0; bottom_size--)
1332 *dstptr = sum / (top_height + bottom_size);
1333 dstptr += width + 1;
1334 sum -= srcptr[-top_height * (width + 1)];
1335 srcptr += width + 1;
1338 /* Done with the column... copy dest back over source */
1340 dstptr = char_grayscale + col;
1341 srcptr = char_grayscale + width; /* scratch */
1342 for (row = 0; row < height; row++)
1345 dstptr += width + 1;
1346 srcptr += width + 1;
1351 /* Increase the grayvalue to increase ink a bit */
1352 srcptr = char_grayscale;
1353 for (row = 0; row < height; row++)
1355 for (col = 0; col < width; col++)
1357 register int pixvalue = (int)*srcptr * pixmult / 256;
1358 if (pixvalue > 255) pixvalue = 255;
1366 /* Compute the increment values for the resampling loop */
1367 TRANSFORM_POINT(inv_xform, 1, 0, point);
1368 deltaX = (INT32)(point[0] * 65536.0);
1369 deltaY = (INT32)(-point[1] * 65536.0);
1371 /* Resampling loop: resamples original glyph for generation of new
1372 glyph in transformed coordinate system. */
1374 for (row = 0; row < newHeight; row++)
1376 /* Compute inverse transformation for start of this row */
1377 TRANSFORM_POINT(inv_xform,
1378 (double)(pci->metrics.leftSideBearing) + .5,
1379 (double)(pci->metrics.ascent - row) - .5,
1382 /* Adjust for coordinate system to get resampling point */
1383 point[0] -= opci->metrics.leftSideBearing;
1384 point[1] = opci->metrics.ascent - point[1];
1386 /* Convert to integer coordinates */
1387 xValue = (INT32)(point[0] * 65536.0);
1388 yValue = (INT32)(point[1] * 65536.0);
1393 for (col = 0; col < newWidth; col++)
1395 register int x = xValue >> 16, y = yValue >> 16;
1396 int pixvalue, error;
1398 pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ?
1399 char_grayscale[x + y * (width + 1)] : 0) +
1401 if (pixvalue > 255) pixvalue = 255;
1402 else if (pixvalue < 0) pixvalue = 0;
1404 /* Choose the bit value and set resulting error value */
1405 if (pixvalue >= 128)
1407 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
1408 error = pixvalue - 255;
1413 /* Diffuse the error */
1414 thisrow[col + 1] += error * 7;
1415 nextrow[col - 1] += error * 3;
1416 nextrow[col] += error * 5;
1417 nextrow[col + 1] = error;
1423 /* Add in error values that fell off either end */
1424 nextrow[0] += nextrow[-1];
1425 nextrow[newWidth - 2] += thisrow[newWidth];
1426 nextrow[newWidth - 1] += nextrow[newWidth];
1427 nextrow[newWidth] = 0;
1432 nextrow[-1] = nextrow[0] = 0;
1436 for (col = 0; col < newWidth; col++)
1438 register int x = xValue >> 16, y = yValue >> 16;
1440 if (x >= 0 && x < width && y >= 0 && y < height)
1442 /* Use point-sampling for rescaling. */
1444 if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7])
1445 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
1457 free(char_grayscale);
1458 free(diffusion_workspace);
1463 BitmapScaleBitmaps(FontPtr pf, /* scaled font */
1464 FontPtr opf, /* originating font */
1465 double widthMult, /* glyphs width scale factor */
1466 double heightMult, /* glyphs height scale factor */
1467 FontScalablePtr vals)
1472 BitmapFontPtr bitmapFont,
1478 unsigned bytestoalloc = 0;
1479 int firstCol, lastCol, firstRow, lastRow;
1481 double xform[4], inv_xform[4];
1482 double xmult, ymult;
1484 bitmapFont = (BitmapFontPtr) pf->fontPrivate;
1485 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
1487 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
1488 inv_xform, &xmult, &ymult))
1492 firstCol = pfi->firstCol;
1493 lastCol = pfi->lastCol;
1494 firstRow = pfi->firstRow;
1495 lastRow = pfi->lastRow;
1497 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
1499 for (i = 0; i < nchars; i++)
1501 if ((pci = ACCESSENCODING(bitmapFont->encoding, i)))
1502 bytestoalloc += BYTES_FOR_GLYPH(pci, glyph);
1505 /* Do we add the font malloc stuff for VALUE ADDED ? */
1506 /* Will need to remember to free in the Unload routine */
1509 bitmapFont->bitmaps = calloc(1, bytestoalloc);
1510 if (!bitmapFont->bitmaps) {
1511 fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc);
1515 glyphBytes = bitmapFont->bitmaps;
1516 for (i = 0; i < nchars; i++)
1518 if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) &&
1519 (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i))))
1521 pci->bits = glyphBytes;
1522 ScaleBitmap (pf, opci, pci, inv_xform,
1523 widthMult, heightMult);
1524 glyphBytes += BYTES_FOR_GLYPH(pci, glyph);
1533 free(bitmapFont->metrics);
1534 free(bitmapFont->ink_metrics);
1535 free(bitmapFont->bitmaps);
1536 if(bitmapFont->encoding)
1537 for(i=0; i<NUM_SEGMENTS(nchars); i++)
1538 free(bitmapFont->encoding[i]);
1539 free(bitmapFont->encoding);
1546 BitmapOpenScalable (FontPathElementPtr fpe,
1550 char *fileName, /* unused */
1551 FontScalablePtr vals,
1552 fsBitmapFormat format,
1553 fsBitmapFormatMask fmask,
1554 FontPtr non_cachable_font) /* We don't do licensing */
1556 FontScalableRec best;
1557 FontPtr font = NullFont;
1562 char *isStringProp = NULL;
1567 FontEntryPtr scaleFrom;
1568 FontPathElementPtr scaleFPE = NULL;
1570 char fontName[MAXFONTNAMELEN];
1572 /* Can't deal with mix-endian fonts yet */
1575 /* Reject outrageously small font sizes to keep the math from
1577 if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 ||
1578 get_matrix_horizontal_component(vals->pixel_matrix) < 1.0)
1581 scaleFrom = FindBestToScale(fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy,
1587 status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom,
1590 if (status != Successful)
1594 vals->width = best.width * dx;
1596 /* Compute the scaled font */
1600 font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth);
1602 font = BitmapScaleBitmaps(font, sourceFont, savedX, savedY, vals);
1606 if (!sourceFont->refcnt)
1607 FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
1611 /* Prepare font properties for the new font */
1613 strcpy (fontName, scaleFrom->name.name);
1614 FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE);
1616 propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals,
1617 dx, dy, sdx, sdy, sWidth, &props,
1620 if (!sourceFont->refcnt)
1621 FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
1623 font->info.props = props;
1624 font->info.nprops = propCount;
1625 font->info.isStringProp = isStringProp;
1627 if (propCount && (!props || !isStringProp))
1629 bitmapUnloadScalable(font);
1638 BitmapGetInfoScalable (FontPathElementPtr fpe,
1639 FontInfoPtr pFontInfo,
1641 FontNamePtr fontName,
1643 FontScalablePtr vals)
1647 long format = 0; /* It doesn't matter what format for just info */
1651 ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals,
1652 format, fmask, NULL);
1653 if (ret != Successful)
1655 *pFontInfo = pfont->info;
1657 pfont->info.nprops = 0;
1658 pfont->info.props = NULL;
1659 pfont->info.isStringProp = NULL;
1661 (*pfont->unload_font)(pfont);
1666 bitmapUnloadScalable (FontPtr pFont)
1668 BitmapFontPtr bitmapFont;
1672 bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
1675 free (pfi->isStringProp);
1676 if(bitmapFont->encoding) {
1677 nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
1678 (pFont->info.lastRow - pFont->info.firstRow + 1);
1679 for(i=0; i<NUM_SEGMENTS(nencoding); i++)
1680 free(bitmapFont->encoding[i]);
1682 free (bitmapFont->encoding);
1683 free (bitmapFont->bitmaps);
1684 free (bitmapFont->ink_metrics);
1685 free (bitmapFont->metrics);
1686 free (pFont->fontPrivate);
1687 DestroyFontRec (pFont);