1 /* $TOG: bitscale.c /main/31 1997/06/09 11:21:46 barstow $ */
5 Copyright (c) 1991, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
32 /* $XFree86: xc/lib/font/bitmap/bitscale.c,v 3.4.2.1 1997/06/11 12:08:40 dawes Exp $ */
35 * Author: Keith Packard, MIT X Consortium
43 #define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
49 #define MAX(a,b) (((a)>(b)) ? a : b)
52 extern Atom MakeAtom();
54 void bitmapUnloadScalable();
57 atom, truncate_atom, pixel_size, point_size, resolution_x,
58 resolution_y, average_width, scaledX, scaledY, unscaled, fontname,
59 raw_ascent, raw_descent, raw_pixelsize, raw_pointsize,
60 raw_average_width, uncomputed
63 typedef struct _fontProp {
69 static FontPtr BitmapScaleBitmaps();
70 static FontPtr PrinterScaleBitmaps();
72 typedef FontPtr (*ScaleFunc) ();
73 /* These next two arrays must be kept in step with the renderer array */
85 static FontEntryPtr FindBestToScale();
86 static FontEntryPtr FindPmfToScale();
88 typedef FontEntryPtr (*FindToScale) ();
89 FindToScale find_scale[] =
100 static unsigned long fontGeneration = 0; /* initialization flag */
102 static fontProp fontNamePropTable[] = {
104 "FAMILY_NAME", 0, atom,
105 "WEIGHT_NAME", 0, atom,
107 "SETWIDTH_NAME", 0, atom,
108 "ADD_STYLE_NAME", 0, atom,
109 "PIXEL_SIZE", 0, pixel_size,
110 "POINT_SIZE", 0, point_size,
111 "RESOLUTION_X", 0, resolution_x,
112 "RESOLUTION_Y", 0, resolution_y,
114 "AVERAGE_WIDTH", 0, average_width,
115 "CHARSET_REGISTRY", 0, atom,
116 "CHARSET_ENCODING", 0, truncate_atom,
118 "RAW_ASCENT", 0, raw_ascent,
119 "RAW_DESCENT", 0, raw_descent,
120 "RAW_PIXEL_SIZE", 0, raw_pixelsize,
121 "RAW_POINT_SIZE", 0, raw_pointsize,
122 "RAW_AVERAGE_WIDTH", 0, raw_average_width
125 #define TRANSFORM_POINT(matrix, x, y, dest) \
126 ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
127 (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
129 #define CHECK_EXTENT(lsb, rsb, desc, asc, data) \
130 ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
131 (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
132 (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
133 (asc) < (data)[1] ? (asc) = (data)[1] : 0)
135 #define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp))
137 /* Warning: order of the next two tables is critically interdependent.
138 Location of "unscaled" properties at the end of fontPropTable[]
141 static fontProp fontPropTable[] = {
142 "MIN_SPACE", 0, scaledX,
143 "NORM_SPACE", 0, scaledX,
144 "MAX_SPACE", 0, scaledX,
145 "END_SPACE", 0, scaledX,
146 "AVG_CAPITAL_WIDTH", 0, scaledX,
147 "AVG_LOWERCASE_WIDTH", 0, scaledX,
148 "QUAD_WIDTH", 0, scaledX,
149 "FIGURE_WIDTH", 0, scaledX,
150 "SUPERSCRIPT_X", 0, scaledX,
151 "SUPERSCRIPT_Y", 0, scaledY,
152 "SUBSCRIPT_X", 0, scaledX,
153 "SUBSCRIPT_Y", 0, scaledY,
154 "SUPERSCRIPT_SIZE", 0, scaledY,
155 "SUBSCRIPT_SIZE", 0, scaledY,
156 "SMALL_CAP_SIZE", 0, scaledY,
157 "UNDERLINE_POSITION", 0, scaledY,
158 "UNDERLINE_THICKNESS", 0, scaledY,
159 "STRIKEOUT_ASCENT", 0, scaledY,
160 "STRIKEOUT_DESCENT", 0, scaledY,
161 "CAP_HEIGHT", 0, scaledY,
162 "X_HEIGHT", 0, scaledY,
163 "ITALIC_ANGLE", 0, unscaled,
164 "RELATIVE_SETWIDTH", 0, unscaled,
165 "RELATIVE_WEIGHT", 0, unscaled,
166 "WEIGHT", 0, unscaled,
167 "DESTINATION", 0, unscaled,
168 "PCL_FONT_NAME", 0, unscaled,
169 "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled
172 static fontProp rawFontPropTable[] = {
173 "RAW_MIN_SPACE", 0, 0,
174 "RAW_NORM_SPACE", 0, 0,
175 "RAW_MAX_SPACE", 0, 0,
176 "RAW_END_SPACE", 0, 0,
177 "RAW_AVG_CAPITAL_WIDTH", 0, 0,
178 "RAW_AVG_LOWERCASE_WIDTH", 0, 0,
179 "RAW_QUAD_WIDTH", 0, 0,
180 "RAW_FIGURE_WIDTH", 0, 0,
181 "RAW_SUPERSCRIPT_X", 0, 0,
182 "RAW_SUPERSCRIPT_Y", 0, 0,
183 "RAW_SUBSCRIPT_X", 0, 0,
184 "RAW_SUBSCRIPT_Y", 0, 0,
185 "RAW_SUPERSCRIPT_SIZE", 0, 0,
186 "RAW_SUBSCRIPT_SIZE", 0, 0,
187 "RAW_SMALL_CAP_SIZE", 0, 0,
188 "RAW_UNDERLINE_POSITION", 0, 0,
189 "RAW_UNDERLINE_THICKNESS", 0, 0,
190 "RAW_STRIKEOUT_ASCENT", 0, 0,
191 "RAW_STRIKEOUT_DESCENT", 0, 0,
192 "RAW_CAP_HEIGHT", 0, 0,
193 "RAW_X_HEIGHT", 0, 0,
202 i = sizeof(fontNamePropTable) / sizeof(fontProp);
203 for (t = fontNamePropTable; i; i--, t++)
204 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
206 i = sizeof(fontPropTable) / sizeof(fontProp);
207 for (t = fontPropTable; i; i--, t++)
208 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
210 i = sizeof(rawFontPropTable) / sizeof(fontProp);
211 for (t = rawFontPropTable; i; i--, t++)
212 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
216 GetScalableEntry (fpe, name)
217 FontPathElementPtr fpe;
220 FontDirectoryPtr dir;
222 dir = (FontDirectoryPtr) fpe->private;
223 return FontFileFindNameInDir (&dir->scalable, name);
227 get_matrix_horizontal_component(matrix)
230 return hypot(matrix[0], matrix[1]);
234 get_matrix_vertical_component(matrix)
237 return hypot(matrix[2], matrix[3]);
242 ComputeScaleFactors(from, to, dx, dy, sdx, sdy, rescale_x)
243 FontScalablePtr from,
249 double srcpixelset, destpixelset, srcpixel, destpixel;
251 srcpixelset = get_matrix_horizontal_component(from->pixel_matrix);
252 destpixelset = get_matrix_horizontal_component(to->pixel_matrix);
253 srcpixel = get_matrix_vertical_component(from->pixel_matrix);
254 destpixel = get_matrix_vertical_component(to->pixel_matrix);
256 if (srcpixelset >= EPS)
258 *dx = destpixelset / srcpixelset;
259 *sdx = 1000.0 / srcpixelset;
266 /* If client specified a width, it overrides setsize; in this
267 context, we interpret width as applying to the font before any
268 rotation, even though that's not what is ultimately returned in
270 if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS)
272 double rescale = (double)to->width / (double)from->width;
274 /* If the client specified a transformation matrix, the rescaling
275 for width does *not* override the setsize. Instead, just check
276 for consistency between the setsize from the matrix and the
277 setsize that would result from rescaling according to the width.
278 This assumes (perhaps naively) that the width is correctly
279 reported in the name. As an interesting side effect, this test
280 may result in choosing a different source bitmap (one that
281 scales consistently between the setsize *and* the width) than it
282 would choose if a width were not specified. Sort of a hidden
283 multiple-master functionality. */
284 if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
285 (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
287 /* Reject if resulting width difference is >= 1 pixel */
288 if (fabs(rescale * from->width - *dx * from->width) >= 10)
293 *rescale_x = rescale/(*dx);
300 *dy = destpixel / srcpixel;
301 *sdy = 1000.0 / srcpixel;
309 /* favor enlargement over reduction because of aliasing resulting
318 score += (int)(((double)(3 * s)) / m); \
320 score += (int)(((double)(2 * s)) * m); \
323 /* don't need to favor enlargement when looking for bitmap that can
324 be used unscalable */
325 #define SCORE2(m,s) \
327 score += (int)(((double)(8 * s)) / m); \
329 score += (int)(((double)(8 * s)) * m);
332 FindBestToScale(fpe, entry, vals, best, dxp, dyp, sdxp, sdyp, fpep)
333 FontPathElementPtr fpe;
335 FontScalablePtr vals,
339 FontPathElementPtr *fpep;
341 FontScalableRec temp;
343 int best_score, best_unscaled_score,
345 double dx, sdx, dx_amount,
347 best_dx, best_sdx, best_dx_amount,
348 best_dy, best_sdy, best_dy_amount,
349 best_unscaled_sdx, best_unscaled_sdy,
350 rescale_x, best_rescale_x,
351 best_unscaled_rescale_x;
353 FontNameRec zeroName;
354 char zeroChars[MAXFONTNAMELEN];
355 FontDirectoryPtr dir;
356 FontScaledPtr scaled;
357 FontScalableExtraPtr extra;
358 FontScaledPtr best_scaled, best_unscaled;
359 FontPathElementPtr best_fpe, best_unscaled_fpe;
360 FontEntryPtr bitmap = NULL;
363 FontPathElementPtr bitmap_fpe;
364 FontNameRec xlfdName;
366 /* find the best match */
371 best_unscaled_score = -1;
372 memcpy (zeroChars, entry->name.name, entry->name.length);
373 zeroChars[entry->name.length] = '\0';
374 zeroName.name = zeroChars;
375 FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO);
376 zeroName.length = strlen (zeroChars);
377 zeroName.ndashes = entry->name.ndashes;
378 xlfdName.name = vals->xlfdName;
379 xlfdName.length = strlen(xlfdName.name);
380 xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length);
381 restart_bestscale_loop: ;
383 * Look through all the registered bitmap sources for
384 * the same zero name as ours; entries along that one
385 * can be scaled as desired.
387 for (source = 0; source < FontFileBitmapSources.count; source++)
389 /* There might already be a bitmap that satisfies the request
390 but didn't have a zero name that was found by the scalable
391 font matching logic. Keep track if there is. */
392 if (bitmap == NULL && vals->xlfdName != NULL)
394 bitmap_fpe = FontFileBitmapSources.fpe[source];
395 dir = (FontDirectoryPtr) bitmap_fpe->private;
396 bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName);
397 if (bitmap && bitmap->type != FONT_ENTRY_BITMAP)
399 if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0)
402 xlfdName.name = bitmap->u.alias.resolved;
403 xlfdName.length = strlen(xlfdName.name);
404 xlfdName.ndashes = FontFileCountDashes(xlfdName.name,
407 goto restart_bestscale_loop;
414 if (FontFileBitmapSources.fpe[source] == fpe)
418 dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
419 zero = FontFileFindNameInDir (&dir->scalable, &zeroName);
423 extra = zero->u.scalable.extra;
424 for (i = 0; i < extra->numScaled; i++)
426 FontScalableRec tmpvals;
427 scaled = &extra->scaled[i];
430 if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy,
436 SCORE(dy_amount, 10);
438 if ((score > best_score) ||
439 ((score == best_score) &&
440 ((dy_amount < best_dy_amount) ||
441 ((dy_amount == best_dy_amount) &&
442 (dx_amount < best_dx_amount)))))
444 best_fpe = FontFileBitmapSources.fpe[source];
445 best_scaled = scaled;
451 best_dx_amount = dx_amount;
452 best_dy_amount = dy_amount;
453 best_rescale_x = rescale_x;
455 /* Is this font a candidate for use without ugly rescaling? */
456 if (fabs(dx) > EPS && fabs(dy) > EPS &&
457 fabs(vals->pixel_matrix[0] * rescale_x -
458 scaled->vals.pixel_matrix[0]) < 1 &&
459 fabs(vals->pixel_matrix[1] * rescale_x -
460 scaled->vals.pixel_matrix[1]) < EPS &&
461 fabs(vals->pixel_matrix[2] -
462 scaled->vals.pixel_matrix[2]) < EPS &&
463 fabs(vals->pixel_matrix[3] -
464 scaled->vals.pixel_matrix[3]) < 1)
466 /* Yes. The pixel sizes are close on the diagonal and
467 extremely close off the diagonal. */
469 SCORE2(vals->pixel_matrix[3] /
470 scaled->vals.pixel_matrix[3], 10);
471 SCORE2(vals->pixel_matrix[0] * rescale_x /
472 scaled->vals.pixel_matrix[0], 1);
473 if (score > best_unscaled_score)
475 best_unscaled_fpe = FontFileBitmapSources.fpe[source];
476 best_unscaled = scaled;
477 best_unscaled_sdx = sdx / dx;
478 best_unscaled_sdy = sdy / dy;
479 best_unscaled_score = score;
480 best_unscaled_rescale_x = rescale_x;
487 *best = best_unscaled->vals;
488 *fpep = best_unscaled_fpe;
491 *sdxp = best_unscaled_sdx;
492 *sdyp = best_unscaled_sdy;
493 rescale_x = best_unscaled_rescale_x;
494 result = best_unscaled->bitmap;
496 else if (best_scaled)
498 *best = best_scaled->vals;
504 rescale_x = best_rescale_x;
505 result = best_scaled->bitmap;
510 if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0))
513 FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE);
514 if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x))
520 if (result && rescale_x != 1.0)
522 /* We have rescaled horizontally due to an XLFD width field. Change
523 the matrix appropriately */
524 vals->pixel_matrix[0] *= rescale_x;
525 vals->pixel_matrix[1] *= rescale_x;
527 /* This would force the pointsize and pixelsize fields in the
528 FONT property to display as matrices to more accurately
529 report the font being supplied. It might also break existing
530 applications that expect a single number in that field. */
531 vals->values_supplied =
532 vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) |
535 vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK;
537 /* Recompute and reround the FontScalablePtr values after
538 rescaling for the new width. */
539 FontFileCompleteXLFD(vals, vals);
546 FindPmfToScale(fpe, entry, vals, best, dxp, dyp, sdxp, sdyp, fpep)
547 FontPathElementPtr fpe;
549 FontScalablePtr vals,
553 FontPathElementPtr *fpep;
555 FontEntryPtr result = NULL;
556 FontScaledPtr scaled;
557 FontScalableExtraPtr extra;
560 extra = entry->u.scalable.extra;
561 for (i = 0; i < extra->numScaled; i++)
565 scaled = &extra->scaled[i];
568 if (!ComputeScaleFactors(&scaled->vals, vals, dxp, dyp, sdxp, sdyp,
571 *best = scaled->vals;
573 result = scaled->bitmap;
574 if (rescale_x != 1.0)
576 /* We have rescaled horizontally due to an XLFD width field. Change
577 the matrix appropriately */
578 vals->pixel_matrix[0] *= rescale_x;
579 vals->pixel_matrix[1] *= rescale_x;
581 /* This would force the pointsize and pixelsize fields in the
582 FONT property to display as matrices to more accurately
583 report the font being supplied. It might also break existing
584 applications that expect a single number in that field. */
585 vals->values_supplied =
586 vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) |
589 vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK;
591 /* Recompute and reround the FontScalablePtr values after
592 rescaling for the new width. */
593 FontFileCompleteXLFD(vals, vals);
604 return (x >= 0) ? (long)(x + .5) : (long)(x - .5);
608 computeProps(pf, wasStringProp, npf, isStringProp, nprops, xfactor, yfactor,
615 double xfactor, sXfactor,
623 for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) {
624 n = sizeof(fontPropTable) / sizeof(fontProp);
625 for (t = fontPropTable; n && (t->atom != pf->name); n--, t++);
631 npf->value = doround(xfactor * (double)pf->value);
632 rawfactor = sXfactor;
635 npf->value = doround(yfactor * (double)pf->value);
636 rawfactor = sYfactor;
639 npf->value = pf->value;
640 npf->name = pf->name;
643 *isStringProp++ = *wasStringProp;
646 if (t->type != unscaled)
648 npf->name = pf->name;
651 npf->value = doround(rawfactor * (double)pf->value);
652 npf->name = rawFontPropTable[t - fontPropTable].atom;
655 *isStringProp++ = *wasStringProp;
656 *isStringProp++ = *wasStringProp;
664 ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, sdx, sdy,
665 sWidth, pProps, pIsStringProp)
666 FontInfoPtr sourceFontInfo; /* the font to be scaled */
667 char *name; /* name of resulting font */
668 FontScalablePtr vals;
670 dy, sdy; /* scale factors in x and y directions */
671 long sWidth; /* 1000-pixel average width */
672 FontPropPtr *pProps; /* returns properties; preallocated */
673 char **pIsStringProp; /* return booleans; preallocated */
681 extern int serverGeneration;
685 if (fontGeneration != serverGeneration) {
687 fontGeneration = serverGeneration;
689 nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) +
690 sizeof(rawFontPropTable) / sizeof(fontProp);
691 fp = (FontPropPtr) xalloc(sizeof(FontPropRec) * nProps);
695 isStringProp = (char *) xalloc (nProps);
696 *pIsStringProp = isStringProp;
703 for (fpt = fontNamePropTable, n = NPROPS;
705 fp++, fpt++, n--, isStringProp++)
711 if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0');
717 fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE);
721 for (ptr3 = ptr1; *ptr3; ptr3++)
724 if (!*ptr3) ptr3 = ptr2;
725 fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE);
729 fp->value = doround(vals->pixel_matrix[3]);
732 fp->value = doround(vals->point_matrix[3] * 10.0);
741 fp->value = vals->width;
744 fp->value = MakeAtom(name, strlen(name), TRUE);
748 fp->value = sourceFontInfo->fontAscent * sdy;
751 fp->value = sourceFontInfo->fontDescent * sdy;
754 fp->value = (long)(72270.0 / (double)vals->y + .5);
759 case raw_average_width:
763 fp->name = fpt->atom;
766 n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
767 fp, isStringProp, sourceFontInfo->nprops, dx, dy,
772 static void ScaleBitmap();
775 compute_xform_matrix(vals, dx, dy, xform, inv_xform, xmult, ymult)
776 FontScalablePtr vals;
777 double dx, dy, *inv_xform, *xmult, *ymult;
778 register double *xform;
780 double det, sintheta, costheta, tanphi;
781 double pixel = get_matrix_vertical_component(vals->pixel_matrix);
782 double pixelset = get_matrix_horizontal_component(vals->pixel_matrix);
784 if (pixel < EPS || pixelset < EPS) return 0;
786 /* Initialize the transformation matrix to the scaling factors */
787 xform[0] = dx / pixelset;
788 xform[1] = xform[2] = 0.0;
789 xform[3] = dy / pixel;
791 /* Inline matrix multiply -- somewhat ugly to minimize register usage */
792 #define MULTIPLY_XFORM(a,b,c,d) \
794 register double aa = (a), bb = (b), cc = (c), dd = (d); \
795 register double temp; \
796 temp = aa * xform[0] + cc * xform[1]; \
797 aa = aa * xform[2] + cc * xform[3]; \
798 xform[1] = bb * xform[0] + dd * xform[1]; \
799 xform[3] = bb * xform[2] + dd * xform[3]; \
804 /* Rescale the transformation matrix for size of source font */
805 MULTIPLY_XFORM(vals->pixel_matrix[0],
806 vals->pixel_matrix[1],
807 vals->pixel_matrix[2],
808 vals->pixel_matrix[3]);
814 if (inv_xform == NULL) return 1;
816 /* Compute the determinant for use in inverting the matrix. */
817 det = xform[0] * xform[3] - xform[1] * xform[2];
819 /* If the determinant is tiny or zero, give up */
820 if (fabs(det) < EPS) return 0;
822 /* Compute the inverse */
823 inv_xform[0] = xform[3] / det;
824 inv_xform[1] = -xform[1] / det;
825 inv_xform[2] = -xform[2] / det;
826 inv_xform[3] = xform[0] / det;
833 * returns a pointer to the new scaled font, or NULL (due to AllocError).
836 ScaleFont(opf, widthMult, heightMult, sWidthMult, sHeightMult, vals,
837 newWidthMult, newHeightMult, sWidth)
838 FontPtr opf; /* originating font */
839 double widthMult; /* glyphs width scale factor */
840 double heightMult; /* glyphs height scale factor */
841 double sWidthMult; /* scalable glyphs width scale factor */
842 double sHeightMult; /* scalable glyphs height scale factor */
843 FontScalablePtr vals;
844 double *newWidthMult; /* return: X component of glyphs width
846 double *newHeightMult; /* return: Y component of glyphs height
848 long *sWidth; /* return: average 1000-pixel width */
853 BitmapFontPtr bitmapFont,
857 int nchars; /* how many characters in the font */
861 int firstCol, lastCol, firstRow, lastRow;
862 double xform[4], inv_xform[4];
864 int totalwidth = 0, totalchars = 0;
865 int inkindex1, inkindex2;
866 #define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \
867 firstRow - opf->info.firstRow) * \
868 (opf->info.lastCol - opf->info.firstCol + 1) + \
869 (i)%(lastCol - firstCol + 1) + \
870 firstCol - opf->info.firstCol)
872 extern int bitmapGetBitmaps();
873 extern int bitmapGetExtents();
874 extern int bitmapGetGlyphs();
875 extern int bitmapGetMetrics();
881 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
884 pf = (FontPtr) xalloc(sizeof(FontRec));
889 pf->devPrivates = (pointer *) 0;
891 pf->byte = opf->byte;
892 pf->glyph = opf->glyph;
893 pf->scan = opf->scan;
895 pf->get_glyphs = bitmapGetGlyphs;
896 pf->get_metrics = bitmapGetMetrics;
897 pf->unload_font = bitmapUnloadScalable;
898 pf->unload_glyphs = NULL;
902 /* If charset subsetting specified in vals, determine what our range
903 needs to be for the output font */
914 for (i = 0; i < vals->nranges; i++)
916 if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high)
918 firstCol = opfi->firstCol;
919 lastCol = opfi->lastCol;
921 if (firstCol > vals->ranges[i].min_char_low)
922 firstCol = vals->ranges[i].min_char_low;
923 if (lastCol < vals->ranges[i].max_char_low)
924 lastCol = vals->ranges[i].max_char_low;
925 if (firstRow > vals->ranges[i].min_char_high)
926 firstRow = vals->ranges[i].min_char_high;
927 if (lastRow < vals->ranges[i].max_char_high)
928 lastRow = vals->ranges[i].max_char_high;
931 if (firstCol > lastCol || firstRow > lastRow)
934 if (firstCol < opfi->firstCol)
935 firstCol = opfi->firstCol;
936 if (lastCol > opfi->lastCol)
937 lastCol = opfi->lastCol;
938 if (firstRow < opfi->firstRow)
939 firstRow = opfi->firstRow;
940 if (lastRow > opfi->lastRow)
941 lastRow = opfi->lastRow;
945 firstCol = opfi->firstCol;
946 lastCol = opfi->lastCol;
947 firstRow = opfi->firstRow;
948 lastRow = opfi->lastRow;
951 bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec));
954 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
955 pfi->firstRow = firstRow;
956 pfi->lastRow = lastRow;
957 pfi->firstCol = firstCol;
958 pfi->lastCol = lastCol;
959 pf->fontPrivate = (pointer) bitmapFont;
960 bitmapFont->version_num = obitmapFont->version_num;
961 bitmapFont->num_chars = nchars;
962 bitmapFont->num_tables = obitmapFont->num_tables;
963 bitmapFont->metrics = 0;
964 bitmapFont->ink_metrics = 0;
965 bitmapFont->bitmaps = 0;
966 bitmapFont->encoding = 0;
967 bitmapFont->bitmapExtra = 0;
968 bitmapFont->pDefault = 0;
969 bitmapFont->metrics = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec));
970 if (!bitmapFont->metrics)
972 bitmapFont->encoding = (CharInfoPtr *) xalloc(nchars * sizeof(CharInfoPtr));
973 if (!bitmapFont->encoding)
977 #define MAXSHORT 32767
979 #define MINSHORT -32768
981 pfi->anamorphic = FALSE;
982 if (heightMult != widthMult)
983 pfi->anamorphic = TRUE;
984 pfi->cachable = TRUE;
986 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
987 inv_xform, &xmult, &ymult))
990 pfi->fontAscent = opfi->fontAscent * ymult;
991 pfi->fontDescent = opfi->fontDescent * ymult;
993 pfi->minbounds.leftSideBearing = MAXSHORT;
994 pfi->minbounds.rightSideBearing = MAXSHORT;
995 pfi->minbounds.ascent = MAXSHORT;
996 pfi->minbounds.descent = MAXSHORT;
997 pfi->minbounds.characterWidth = MAXSHORT;
998 pfi->minbounds.attributes = MAXSHORT;
1000 pfi->maxbounds.leftSideBearing = MINSHORT;
1001 pfi->maxbounds.rightSideBearing = MINSHORT;
1002 pfi->maxbounds.ascent = MINSHORT;
1003 pfi->maxbounds.descent = MINSHORT;
1004 pfi->maxbounds.characterWidth = MINSHORT;
1005 pfi->maxbounds.attributes = MINSHORT;
1007 /* Compute the transformation and inverse transformation matrices.
1008 Can fail if the determinant is zero. */
1011 pci = bitmapFont->metrics;
1012 for (i = 0; i < nchars; i++)
1014 if (opci = obitmapFont->encoding[inkindex2 = OLDINDEX(i)])
1016 double newlsb, newrsb, newdesc, newasc, point[2];
1018 #define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
1019 #define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
1023 int row = i / (lastCol - firstCol + 1) + firstRow;
1024 int col = i % (lastCol - firstCol + 1) + firstCol;
1025 int ch = (row << 8) + col;
1027 for (j = 0; j < vals->nranges; j++)
1028 if (ch >= minchar(vals->ranges[j]) &&
1029 ch <= maxchar(vals->ranges[j]))
1031 if (j == vals->nranges)
1033 bitmapFont->encoding[i] = 0;
1038 if (opci->metrics.leftSideBearing == 0 &&
1039 opci->metrics.rightSideBearing == 0 &&
1040 opci->metrics.ascent == 0 &&
1041 opci->metrics.descent == 0 &&
1042 opci->metrics.characterWidth == 0)
1044 bitmapFont->encoding[i] = 0;
1048 bitmapFont->encoding[i] = pci;
1050 /* Compute new extents for this glyph */
1051 TRANSFORM_POINT(xform,
1052 opci->metrics.leftSideBearing,
1053 -opci->metrics.descent,
1057 newdesc = -point[1];
1059 TRANSFORM_POINT(xform,
1060 opci->metrics.leftSideBearing,
1061 opci->metrics.ascent,
1063 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
1064 TRANSFORM_POINT(xform,
1065 opci->metrics.rightSideBearing,
1066 -opci->metrics.descent,
1068 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
1069 TRANSFORM_POINT(xform,
1070 opci->metrics.rightSideBearing,
1071 opci->metrics.ascent,
1073 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
1075 pci->metrics.leftSideBearing = (int)floor(newlsb);
1076 pci->metrics.rightSideBearing = (int)floor(newrsb + .5);
1077 pci->metrics.descent = (int)ceil(newdesc);
1078 pci->metrics.ascent = (int)floor(newasc + .5);
1079 /* Accumulate total width of characters before transformation,
1080 to ascertain predominant direction of font. */
1081 totalwidth += opci->metrics.characterWidth;
1082 pci->metrics.characterWidth =
1083 doround((double)opci->metrics.characterWidth * xmult);
1084 pci->metrics.attributes =
1085 doround((double)opci->metrics.characterWidth * sWidthMult);
1086 if (!pci->metrics.characterWidth)
1088 /* Since transformation may shrink width, height, and
1089 escapement to zero, make sure existing characters
1090 are not mistaken for undefined characters. */
1092 if (pci->metrics.rightSideBearing ==
1093 pci->metrics.leftSideBearing)
1094 pci->metrics.rightSideBearing++;
1095 if (pci->metrics.ascent == -pci->metrics.descent)
1096 pci->metrics.ascent++;
1102 bitmapFont->encoding[i] = 0;
1107 * For each character, set the per-character metrics, scale the glyph, and
1108 * check per-font minbounds and maxbounds character information.
1111 pci = bitmapFont->metrics;
1112 for (i = 0; i < nchars; i++)
1114 CharInfoRec temppci;
1115 if ((pci = bitmapFont->encoding[i]) &&
1116 (opci = obitmapFont->encoding[OLDINDEX(i)]))
1118 pci = bitmapFont->encoding[i];
1120 *sWidth += abs((int)(INT16)pci->metrics.attributes);
1121 #define MINMAX(field) \
1122 if (pfi->minbounds.field > pci->metrics.field) \
1123 pfi->minbounds.field = pci->metrics.field; \
1124 if (pfi->maxbounds.field < pci->metrics.field) \
1125 pfi->maxbounds.field = pci->metrics.field
1127 MINMAX(leftSideBearing);
1128 MINMAX(rightSideBearing);
1131 MINMAX(characterWidth);
1133 /* Hack: Cast attributes into a signed quantity. Tread lightly
1134 for now and don't go changing the global Xproto.h file */
1135 if ((INT16)pfi->minbounds.attributes >
1136 (INT16)pci->metrics.attributes)
1137 pfi->minbounds.attributes = pci->metrics.attributes;
1138 if ((INT16)pfi->maxbounds.attributes <
1139 (INT16)pci->metrics.attributes)
1140 pfi->maxbounds.attributes = pci->metrics.attributes;
1144 pfi->ink_minbounds = pfi->minbounds;
1145 pfi->ink_maxbounds = pfi->maxbounds;
1148 *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars;
1151 /* Dominant direction is R->L */
1155 if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth)
1156 vals->width = pfi->minbounds.characterWidth * 10;
1158 vals->width = doround((double)*sWidth * vals->pixel_matrix[0] /
1166 FontComputeInfoAccelerators (pfi);
1168 if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) {
1173 r = pfi->defaultCh >> 8;
1174 c = pfi->defaultCh & 0xFF;
1175 if (pfi->firstRow <= r && r <= pfi->lastRow &&
1176 pfi->firstCol <= c && c <= pfi->lastCol) {
1177 cols = pfi->lastCol - pfi->firstCol + 1;
1178 r = r - pfi->firstRow;
1179 c = c - pfi->firstCol;
1180 bitmapFont->pDefault = bitmapFont->encoding[r * cols + c];
1184 *newWidthMult = xmult;
1185 *newHeightMult = ymult;
1191 xfree(bitmapFont->metrics);
1192 xfree(bitmapFont->ink_metrics);
1193 xfree(bitmapFont->bitmaps);
1194 xfree(bitmapFont->encoding);
1200 lcm(a, b) /* least common multiple */
1205 register int larger,
1222 ScaleBitmap(pFont, opci, pci, inv_xform, widthMult, heightMult)
1230 register char *bitmap, /* The bits */
1232 register int bpr, /* Padding information */
1234 int width, /* Extents information */
1238 register int row, /* Loop variables */
1240 INT32 deltaX, /* Increments for resampling loop */
1242 INT32 xValue, /* Subscripts for resampling loop */
1245 unsigned char *char_grayscale = 0;
1246 INT32 *diffusion_workspace, *thisrow, *nextrow, pixmult;
1249 static unsigned char masklsb[] =
1250 { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
1251 static unsigned char maskmsb[] =
1252 { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
1253 unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb);
1256 bitmap = opci->bits;
1257 newBitmap = pci->bits;
1258 width = GLYPHWIDTHPIXELS(opci);
1259 height = GLYPHHEIGHTPIXELS(opci);
1260 newWidth = GLYPHWIDTHPIXELS(pci);
1261 newHeight = GLYPHHEIGHTPIXELS(pci);
1262 if (!newWidth || !newHeight || !width || !height)
1265 bpr = BYTES_PER_ROW(width, pFont->glyph);
1266 newBpr = BYTES_PER_ROW(newWidth, pFont->glyph);
1268 if (widthMult > 0.0 && heightMult > 0.0 &&
1269 (widthMult < 1.0 || heightMult < 1.0))
1271 /* We are reducing in one or both dimensions. In an attempt to
1272 reduce aliasing, we'll antialias by passing the original
1273 glyph through a low-pass box filter (which results in a
1274 grayscale image), then use error diffusion to create bitonal
1275 output in the resampling loop. */
1277 /* First compute the sizes of the box filter */
1278 widthMult = ceil(1.0 / widthMult);
1279 heightMult = ceil(1.0 / heightMult);
1282 if (widthMult < (double)box_x) box_x = (int)widthMult;
1283 if (heightMult < (double)box_y) box_y = (int)heightMult;
1284 /* The pixmult value (below) is used to darken the image before
1285 we perform error diffusion: a necessary concession to the
1286 fact that it's very difficult to generate readable halftoned
1287 glyphs. The degree of darkening is proportional to the size
1288 of the blurring filter, hence inversely proportional to the
1289 darkness of the lightest gray that results from antialiasing.
1290 The result is that characters that exercise this logic (those
1291 generated by reducing from a larger source font) tend to err
1292 on the side of being too bold instead of being too light to
1294 pixmult = box_x * box_y * 192;
1296 if (box_x > 1 || box_y > 1)
1298 /* Looks like we need to anti-alias. Create a workspace to
1299 contain the grayscale character plus an additional row and
1300 column for scratch */
1302 (unsigned char *)xalloc((width + 1) * (height + 1));
1305 diffusion_workspace =
1306 (INT32 *)xalloc((newWidth + 2) * 2 * sizeof(int));
1307 if (!diffusion_workspace)
1309 xfree(char_grayscale);
1310 char_grayscale = (unsigned char *)0;
1312 /* Initialize our error diffusion workspace for later use */
1313 bzero((char *)diffusion_workspace + sizeof(INT32),
1314 (newWidth + 3) * sizeof(int));
1315 thisrow = diffusion_workspace + 1;
1316 nextrow = diffusion_workspace + newWidth + 3;
1323 /* We will be doing antialiasing. First copy the bitmap into
1324 our buffer, mapping input range [0,1] to output range
1326 register unsigned char *srcptr, *dstptr;
1327 srcptr = (unsigned char *)bitmap;
1328 dstptr = char_grayscale;
1329 for (row = 0; row < height; row++)
1331 for (col = 0; col < width; col++)
1332 *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0;
1333 srcptr += bpr; /* On to next row of source */
1334 dstptr++; /* Skip scratch column in dest */
1338 /* Our box filter has a width > 1... let's filter the rows */
1340 int right_width = box_x / 2;
1341 int left_width = box_x - right_width - 1;
1343 for (row = 0; row < height; row++)
1346 int left_size = 0, right_size = 0;
1348 srcptr = char_grayscale + (width + 1) * row;
1349 dstptr = char_grayscale + (width + 1) * height; /* scratch */
1351 /* We've computed the shape of our full box filter. Now
1352 compute the right-hand part of the moving sum */
1353 for (right_size = 0; right_size < right_width; right_size++)
1354 sum += srcptr[right_size];
1356 /* Now start moving the sum, growing the box filter, and
1357 dropping averages into our scratch buffer */
1358 for (left_size = 0; left_size < left_width; left_size++)
1360 sum += srcptr[right_width];
1361 *dstptr++ = sum / (left_size + right_width + 1);
1365 /* The box filter has reached full width... continue
1366 computation of moving average until the right side
1368 for (col = left_size; col + right_size < width; col++)
1370 sum += srcptr[right_width];
1371 *dstptr++ = sum / box_x;
1372 sum -= srcptr[-left_width];
1376 /* Collapse the right side of the box filter */
1377 for (; right_size > 0; right_size--)
1379 *dstptr++ = sum / (left_width + right_size);
1380 sum -= srcptr[-left_width];
1384 /* Done with the row... copy dest back over source */
1385 memmove(char_grayscale + (width + 1) * row,
1386 char_grayscale + (width + 1) * height,
1392 /* Our box filter has a height > 1... let's filter the columns */
1394 int bottom_height = box_y / 2;
1395 int top_height = box_y - bottom_height - 1;
1397 for (col = 0; col < width; col++)
1400 int top_size = 0, bottom_size = 0;
1402 srcptr = char_grayscale + col;
1403 dstptr = char_grayscale + width; /* scratch */
1405 /* We've computed the shape of our full box filter. Now
1406 compute the bottom part of the moving sum */
1407 for (bottom_size = 0;
1408 bottom_size < bottom_height;
1410 sum += srcptr[bottom_size * (width + 1)];
1412 /* Now start moving the sum, growing the box filter, and
1413 dropping averages into our scratch buffer */
1414 for (top_size = 0; top_size < top_height; top_size++)
1416 sum += srcptr[bottom_height * (width + 1)];
1417 *dstptr = sum / (top_size + bottom_height + 1);
1418 dstptr += width + 1;
1419 srcptr += width + 1;
1422 /* The box filter has reached full height... continue
1423 computation of moving average until the bottom
1425 for (row = top_size; row + bottom_size < height; row++)
1427 sum += srcptr[bottom_height * (width + 1)];
1428 *dstptr = sum / box_y;
1429 dstptr += width + 1;
1430 sum -= srcptr[-top_height * (width + 1)];
1431 srcptr += width + 1;
1434 /* Collapse the bottom of the box filter */
1435 for (; bottom_size > 0; bottom_size--)
1437 *dstptr = sum / (top_height + bottom_size);
1438 dstptr += width + 1;
1439 sum -= srcptr[-top_height * (width + 1)];
1440 srcptr += width + 1;
1443 /* Done with the column... copy dest back over source */
1445 dstptr = char_grayscale + col;
1446 srcptr = char_grayscale + width; /* scratch */
1447 for (row = 0; row < height; row++)
1450 dstptr += width + 1;
1451 srcptr += width + 1;
1456 /* Increase the grayvalue to increase ink a bit */
1457 srcptr = char_grayscale;
1458 for (row = 0; row < height; row++)
1460 for (col = 0; col < width; col++)
1462 register int pixvalue = (int)*srcptr * pixmult / 256;
1463 if (pixvalue > 255) pixvalue = 255;
1471 /* Compute the increment values for the resampling loop */
1472 TRANSFORM_POINT(inv_xform, 1, 0, point);
1473 deltaX = (INT32)(point[0] * 65536.0);
1474 deltaY = (INT32)(-point[1] * 65536.0);
1476 /* Resampling loop: resamples original glyph for generation of new
1477 glyph in transformed coordinate system. */
1479 for (row = 0; row < newHeight; row++)
1481 /* Compute inverse transformation for start of this row */
1482 TRANSFORM_POINT(inv_xform,
1483 (double)(pci->metrics.leftSideBearing) + .5,
1484 (double)(pci->metrics.ascent - row) - .5,
1487 /* Adjust for coordinate system to get resampling point */
1488 point[0] -= opci->metrics.leftSideBearing;
1489 point[1] = opci->metrics.ascent - point[1];
1491 /* Convert to integer coordinates */
1492 xValue = (INT32)(point[0] * 65536.0);
1493 yValue = (INT32)(point[1] * 65536.0);
1498 for (col = 0; col < newWidth; col++)
1500 register int x = xValue >> 16, y = yValue >> 16;
1501 int pixvalue, error;
1503 pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ?
1504 char_grayscale[x + y * (width + 1)] : 0) +
1506 if (pixvalue > 255) pixvalue = 255;
1507 else if (pixvalue < 0) pixvalue = 0;
1509 /* Choose the bit value and set resulting error value */
1510 if (pixvalue >= 128)
1512 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
1513 error = pixvalue - 255;
1518 /* Diffuse the error */
1519 thisrow[col + 1] += error * 7;
1520 nextrow[col - 1] += error * 3;
1521 nextrow[col] += error * 5;
1522 nextrow[col + 1] = error;
1528 /* Add in error values that fell off either end */
1529 nextrow[0] += nextrow[-1];
1530 nextrow[newWidth - 2] += thisrow[newWidth];
1531 nextrow[newWidth - 1] += nextrow[newWidth];
1532 nextrow[newWidth] = 0;
1537 nextrow[-1] = nextrow[0] = 0;
1541 for (col = 0; col < newWidth; col++)
1543 register int x = xValue >> 16, y = yValue >> 16;
1545 if (x >= 0 && x < width && y >= 0 && y < height)
1547 /* Use point-sampling for rescaling. */
1549 if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7])
1550 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
1562 xfree(char_grayscale);
1563 xfree(diffusion_workspace);
1568 BitmapScaleBitmaps(pf, opf, widthMult, heightMult, vals)
1569 FontPtr pf; /* scaled font */
1570 FontPtr opf; /* originating font */
1571 double widthMult; /* glyphs width scale factor */
1572 double heightMult; /* glyphs height scale factor */
1573 FontScalablePtr vals;
1578 BitmapFontPtr bitmapFont,
1584 unsigned bytestoalloc = 0;
1585 int firstCol, lastCol, firstRow, lastRow;
1587 double xform[4], inv_xform[4];
1588 double xmult, ymult;
1590 bitmapFont = (BitmapFontPtr) pf->fontPrivate;
1591 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
1593 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
1594 inv_xform, &xmult, &ymult))
1598 firstCol = pfi->firstCol;
1599 lastCol = pfi->lastCol;
1600 firstRow = pfi->firstRow;
1601 lastRow = pfi->lastRow;
1603 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
1605 for (i = 0; i < nchars; i++)
1607 if (pci = bitmapFont->encoding[i])
1608 bytestoalloc += BYTES_FOR_GLYPH(pci, glyph);
1611 /* Do we add the font malloc stuff for VALUE ADDED ? */
1612 /* Will need to remember to free in the Unload routine */
1615 bitmapFont->bitmaps = (char *) xalloc(bytestoalloc);
1616 if (!bitmapFont->bitmaps)
1618 bzero(bitmapFont->bitmaps, bytestoalloc);
1620 glyphBytes = bitmapFont->bitmaps;
1621 for (i = 0; i < nchars; i++)
1623 if ((pci = bitmapFont->encoding[i]) &&
1624 (opci = obitmapFont->encoding[OLDINDEX(i)]))
1626 pci->bits = glyphBytes;
1627 ScaleBitmap (pf, opci, pci, inv_xform,
1628 widthMult, heightMult);
1629 glyphBytes += BYTES_FOR_GLYPH(pci, glyph);
1638 xfree(bitmapFont->metrics);
1639 xfree(bitmapFont->ink_metrics);
1640 xfree(bitmapFont->bitmaps);
1641 xfree(bitmapFont->encoding);
1647 PrinterScaleBitmaps(pf, opf, widthMult, heightMult, vals)
1648 FontPtr pf; /* scaled font */
1649 FontPtr opf; /* originating font */
1650 double widthMult; /* glyphs width scale factor */
1651 double heightMult; /* glyphs height scale factor */
1652 FontScalablePtr vals;
1657 BitmapFontPtr bitmapFont,
1663 unsigned bytestoalloc = 0;
1664 int firstCol, lastCol, firstRow, lastRow;
1666 double xform[4], inv_xform[4];
1667 double xmult, ymult;
1669 bitmapFont = (BitmapFontPtr) pf->fontPrivate;
1670 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
1672 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
1673 inv_xform, &xmult, &ymult))
1677 firstCol = pfi->firstCol;
1678 lastCol = pfi->lastCol;
1679 firstRow = pfi->firstRow;
1680 lastRow = pfi->lastRow;
1682 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
1684 for (i = 0; i < nchars; i++)
1686 if (pci = bitmapFont->encoding[i])
1687 bytestoalloc = MAX(bytestoalloc,BYTES_FOR_GLYPH(pci, glyph));
1690 /* Do we add the font malloc stuff for VALUE ADDED ? */
1691 /* Will need to remember to free in the Unload routine */
1694 bitmapFont->bitmaps = (char *) xalloc(bytestoalloc);
1695 if (!bitmapFont->bitmaps)
1697 bzero(bitmapFont->bitmaps, bytestoalloc);
1699 glyphBytes = bitmapFont->bitmaps;
1700 for (i = 0; i < nchars; i++)
1702 if ((pci = bitmapFont->encoding[i]) &&
1703 (opci = obitmapFont->encoding[OLDINDEX(i)]))
1705 pci->bits = glyphBytes;
1714 xfree(bitmapFont->metrics);
1715 xfree(bitmapFont->ink_metrics);
1716 xfree(bitmapFont->bitmaps);
1717 xfree(bitmapFont->encoding);
1724 * exported interfaces
1727 FontFileLoadName(dirs, ndirs, name, pfont, format, fmask)
1728 FontFileDirPtr *dirs;
1732 fsBitmapFormat format;
1733 fsBitmapFormatMask fmask;
1735 FontFileNamePtr fname;
1736 char full_name[1024];
1737 int ret = BadFontName;
1742 if (fname = FontFileFindNameInDir(dirs[i], name)) {
1743 if (!fname->alias) {
1745 strcpy(full_name, dirs[i]->dir);
1746 strcat(full_name, fname->file);
1747 ret = FontFileLoad(pfont, full_name, format, fmask);
1748 if (ret == Successful) {
1749 fname->font = *pfont;
1750 (*pfont)->fpePrivate = (pointer) fname;
1754 *pfont = fname->font;
1767 BitmapOpenScalable (fpe, pFont, flags, entry, fileName, vals, format, fmask,
1769 FontPathElementPtr fpe;
1773 char *fileName; /* unused */
1774 FontScalablePtr vals;
1775 fsBitmapFormat format;
1776 fsBitmapFormatMask fmask;
1777 FontPtr non_cachable_font; /* We don't do licensing */
1779 FontScalableRec best;
1780 FontPtr font = NullFont;
1790 FontEntryPtr scaleFrom;
1791 FontPathElementPtr scaleFPE;
1793 char fontName[MAXFONTNAMELEN];
1795 /* Can't deal with mix-endian fonts yet */
1797 #ifdef NOTDEF /* XXX need better test */
1798 if ((format & BitmapFormatByteOrderMask) !=
1799 (format & BitmapFormatBitOrderMask))
1800 return NullFontFileName;
1803 /* Reject outrageously small font sizes to keep the math from
1805 if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 ||
1806 get_matrix_horizontal_component(vals->pixel_matrix) < 1.0)
1809 scaleFrom = (*find_scale[BitmapGetRenderIndex(entry->u.bitmap.renderer)])
1810 (fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy, &scaleFPE);
1815 status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom,
1818 if (status != Successful)
1822 vals->width = best.width * dx;
1824 /* Compute the scaled font */
1828 font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth);
1830 font = (*scale[ BitmapGetRenderIndex(entry->u.bitmap.renderer) ])
1831 (font, sourceFont, savedX, savedY, vals);
1835 if (!sourceFont->refcnt)
1836 FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
1840 /* Prepare font properties for the new font */
1842 strcpy (fontName, scaleFrom->name.name);
1843 FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE);
1845 propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals,
1846 dx, dy, sdx, sdy, sWidth, &props,
1849 if (!sourceFont->refcnt)
1850 FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
1852 if (propCount && (!props || !isStringProp))
1854 font->info.nprops = 0;
1855 font->info.props = (FontPropPtr)0;
1856 font->info.isStringProp = (char *)0;
1857 bitmapUnloadScalable(font);
1861 font->info.props = props;
1862 font->info.nprops = propCount;
1863 font->info.isStringProp = isStringProp;
1869 BitmapGetInfoScalable (fpe, pFontInfo, entry, fontName, fileName, vals)
1870 FontPathElementPtr fpe;
1871 FontInfoPtr pFontInfo;
1873 FontNamePtr fontName;
1875 FontScalablePtr vals;
1879 long format = 0; /* It doesn't matter what format for just info */
1883 ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals,
1884 format, fmask, NULL);
1885 if (ret != Successful)
1887 *pFontInfo = pfont->info;
1889 pfont->info.props = NULL;
1890 pfont->info.isStringProp = NULL;
1892 (*pfont->unload_font)(pfont);
1897 bitmapUnloadScalable (pFont)
1900 BitmapFontPtr bitmapFont;
1903 bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
1906 xfree (pfi->isStringProp);
1907 xfree (bitmapFont->encoding);
1908 xfree (bitmapFont->bitmaps);
1909 xfree (bitmapFont->ink_metrics);
1910 xfree (bitmapFont->metrics);
1911 xfree (pFont->fontPrivate);
1912 xfree (pFont->devPrivates);