diff options
author | gildea <empty> | 1993-08-24 18:48:45 +0000 |
---|---|---|
committer | gildea <empty> | 1993-08-24 18:48:45 +0000 |
commit | 9048cf6bfb9b5f3e02648efb14bd2aac9423d641 (patch) | |
tree | ad165900172f0288545ef56f22263a0c35825422 /xc/lib/font/bitmap | |
parent | 8214a8d0315029e24214b802065067054822101a (diff) |
Nathan Meyers: XLFD matrix, glyph caching, font auth
Diffstat (limited to 'xc/lib/font/bitmap')
-rw-r--r-- | xc/lib/font/bitmap/bdfread.c | 4 | ||||
-rw-r--r-- | xc/lib/font/bitmap/bitmapfunc.c | 11 | ||||
-rw-r--r-- | xc/lib/font/bitmap/bitscale.c | 1319 | ||||
-rw-r--r-- | xc/lib/font/bitmap/pcfread.c | 4 | ||||
-rw-r--r-- | xc/lib/font/bitmap/snfread.c | 5 |
5 files changed, 880 insertions, 463 deletions
diff --git a/xc/lib/font/bitmap/bdfread.c b/xc/lib/font/bitmap/bdfread.c index 4e2eae14f..f8865b576 100644 --- a/xc/lib/font/bitmap/bdfread.c +++ b/xc/lib/font/bitmap/bdfread.c @@ -22,7 +22,7 @@ SOFTWARE. ************************************************************************/ -/* $XConsortium: bdfread.c,v 1.14 92/05/29 17:10:11 gildea Exp $ */ +/* $XConsortium: bdfread.c,v 1.15 92/11/18 21:30:59 gildea Exp $ */ #include <ctype.h> #include "fontfilest.h" @@ -775,6 +775,7 @@ bdfReadFont(pFont, file, bit, byte, glyph, scan) pFont->glyph = glyph; pFont->scan = scan; pFont->info.anamorphic = FALSE; + pFont->info.cachable = TRUE; bitmapComputeFontBounds(pFont); if (FontCouldBeTerminal(&pFont->info)) { bdfPadToTerminal(pFont); @@ -809,6 +810,7 @@ bdfReadFont(pFont, file, bit, byte, glyph, scan) pFont->get_glyphs = bitmapGetGlyphs; pFont->get_metrics = bitmapGetMetrics; pFont->unload_font = bdfUnloadFont; + pFont->unload_glyphs = NULL; return Successful; BAILOUT: if (pFont->fontPrivate) diff --git a/xc/lib/font/bitmap/bitmapfunc.c b/xc/lib/font/bitmap/bitmapfunc.c index a9c2df0c2..aff6e4bd4 100644 --- a/xc/lib/font/bitmap/bitmapfunc.c +++ b/xc/lib/font/bitmap/bitmapfunc.c @@ -1,5 +1,5 @@ /* - * $XConsortium: bitmapfuncs.c,v 1.3 91/06/12 14:35:17 keith Exp $ + * $XConsortium: bitmapfuncs.c,v 1.4 91/09/07 11:59:18 keith Exp $ * * Copyright 1991 Massachusetts Institute of Technology * @@ -51,25 +51,34 @@ static BitmapFileFunctionsRec readers[] = { bdfReadFont, bdfReadFontInfo, }; + +#define CAPABILITIES (CAP_MATRIX | CAP_CHARSUBSETTING) + static FontRendererRec renderers[] = { ".pcf", 4, BitmapOpenBitmap, BitmapOpenScalable, BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES, ".pcf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES, ".snf", 4, BitmapOpenBitmap, BitmapOpenScalable, BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES, ".snf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES, ".bdf", 4, BitmapOpenBitmap, BitmapOpenScalable, BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES, ".bdf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES, }; BitmapOpenBitmap (fpe, ppFont, flags, entry, fileName, format, fmask) diff --git a/xc/lib/font/bitmap/bitscale.c b/xc/lib/font/bitmap/bitscale.c index ecc224de8..f719d85c3 100644 --- a/xc/lib/font/bitmap/bitscale.c +++ b/xc/lib/font/bitmap/bitscale.c @@ -1,5 +1,5 @@ /* - * $XConsortium: bitscale.c,v 1.11 92/05/12 18:07:44 gildea Exp $ + * $XConsortium: bitscale.c,v 1.12 92/05/29 17:10:15 gildea Exp $ * * Copyright 1991 Massachusetts Institute of Technology * @@ -26,12 +26,15 @@ #include "fontfilest.h" #include "bitmap.h" +#include <math.h> extern Atom MakeAtom(); enum scaleType { - atom, pixel_size, point_size, resolution_x, resolution_y, average_width, - scaledX, scaledY, unscaled, scaledXoverY, uncomputed + atom, truncate_atom, pixel_size, point_size, resolution_x, + resolution_y, average_width, scaledX, scaledY, unscaled, + fontname, raw_ascent, raw_descent, raw_pixelsize, raw_pointsize, + raw_average_width, uncomputed }; typedef struct _fontProp { @@ -45,7 +48,7 @@ static unsigned long fontGeneration = 0; /* initialization flag */ static fontProp fontNamePropTable[] = { "FOUNDRY", 0, atom, "FAMILY_NAME", 0, atom, - "WEIGHT_NAME", 0, atom, + "WEIGHT_NAME", 0, truncate_atom, "SLANT", 0, atom, "SETWIDTH_NAME", 0, atom, "ADD_STYLE_NAME", 0, atom, @@ -56,11 +59,30 @@ static fontProp fontNamePropTable[] = { "SPACING", 0, atom, "AVERAGE_WIDTH", 0, average_width, "CHARSET_REGISTRY", 0, atom, - "CHARSET_ENCODING", 0, atom, - "FONT", 0, atom + "CHARSET_ENCODING", 0, truncate_atom, + "FONT", 0, fontname, + "RAW_ASCENT", 0, raw_ascent, + "RAW_DESCENT", 0, raw_descent, + "RAW_PIXELSIZE", 0, raw_pixelsize, + "RAW_POINTSIZE", 0, raw_pointsize, + "RAW_AVERAGE_WIDTH", 0, raw_average_width }; -#define NPROPS ((sizeof(fontNamePropTable) / sizeof(fontProp)) - 1) +#define TRANSFORM_POINT(matrix, x, y, dest) \ + ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ + (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) + +#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ + ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ + (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ + (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ + (asc) < (data)[1] ? (asc) = (data)[1] : 0) + +#define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp)) + +/* Warning: order of the next two tables is critically interdependent. + Location of "unscaled" properties at the end of fontPropTable[] + is important. */ static fontProp fontPropTable[] = { "MIN_SPACE", 0, scaledX, @@ -82,15 +104,39 @@ static fontProp fontPropTable[] = { "UNDERLINE_THICKNESS", 0, scaledY, "STRIKEOUT_ASCENT", 0, scaledY, "STRIKEOUT_DESCENT", 0, scaledY, - "ITALIC_ANGLE", 0, unscaled, "CAP_HEIGHT", 0, scaledY, "X_HEIGHT", 0, scaledY, + "ITALIC_ANGLE", 0, unscaled, "RELATIVE_SETWIDTH", 0, unscaled, "RELATIVE_WEIGHT", 0, unscaled, - "WEIGHT", 0, scaledXoverY, + "WEIGHT", 0, unscaled, "DESTINATION", 0, unscaled }; +static fontProp rawFontPropTable[] = { + "RAW_MIN_SPACE", 0, 0, + "RAW_NORM_SPACE", 0, 0, + "RAW_MAX_SPACE", 0, 0, + "RAW_END_SPACE", 0, 0, + "RAW_AVG_CAPITAL_WIDTH", 0, 0, + "RAW_AVG_LOWERCASE_WIDTH", 0, 0, + "RAW_QUAD_WIDTH", 0, 0, + "RAW_FIGURE_WIDTH", 0, 0, + "RAW_SUPERSCRIPT_X", 0, 0, + "RAW_SUPERSCRIPT_Y", 0, 0, + "RAW_SUBSCRIPT_X", 0, 0, + "RAW_SUBSCRIPT_Y", 0, 0, + "RAW_SUPERSCRIPT_SIZE", 0, 0, + "RAW_SUBSCRIPT_SIZE", 0, 0, + "RAW_SMALL_CAP_SIZE", 0, 0, + "RAW_UNDERLINE_POSITION", 0, 0, + "RAW_UNDERLINE_THICKNESS", 0, 0, + "RAW_STRIKEOUT_ASCENT", 0, 0, + "RAW_STRIKEOUT_DESCENT", 0, 0, + "RAW_CAP_HEIGHT", 0, 0, + "RAW_X_HEIGHT", 0, 0, +}; + static void initFontPropTable() { @@ -104,6 +150,10 @@ initFontPropTable() i = sizeof(fontPropTable) / sizeof(fontProp); for (t = fontPropTable; i; i--, t++) t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); + + i = sizeof(rawFontPropTable) / sizeof(fontProp); + for (t = rawFontPropTable; i; i--, t++) + t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); } static FontEntryPtr @@ -117,61 +167,78 @@ GetScalableEntry (fpe, name) return FontFileFindNameInDir (&dir->scalable, name); } +static double +get_matrix_horizontal_component(matrix) + double *matrix; +{ + return hypot(matrix[0], matrix[1]); +} + +static double +get_matrix_vertical_component(matrix) + double *matrix; +{ + return hypot(matrix[2], matrix[3]); +} + + static void -ComputeScaleFactors(from, to, dx, dy) +ComputeScaleFactors(from, to, dx, dy, sdx, sdy) FontScalablePtr from, to; - double *dx, - *dy; + double *dx, *sdx, + *dy, *sdy; { - /* compute scale factors */ - if (to->pixel == from->pixel) - *dy = 1.0; + double srcpixelset, destpixelset, srcpixel, destpixel; + + srcpixelset = get_matrix_horizontal_component(from->pixel_matrix); + destpixelset = get_matrix_horizontal_component(to->pixel_matrix); + srcpixel = get_matrix_vertical_component(from->pixel_matrix); + destpixel = get_matrix_vertical_component(to->pixel_matrix); + + if (srcpixelset >= EPS) + { + *dx = destpixelset / srcpixelset; + *sdx = 1000.0 / srcpixelset; + } else - *dy = ((double) to->point * to->y) / (from->point * from->y); - *dx = (((double) (to->x * from->y)) / (to->y * from->x)) * *dy; - if (to->width > 0) - *dx = to->width / (from->width * *dx); + *sdx = *dx = 0; + + if (srcpixel >= EPS) + { + *dy = destpixel / srcpixel; + *sdy = 1000.0 / srcpixel; + } + else + *sdy = *dy = 0; } +/* favor enlargement over reduction because of aliasing resulting + from reduction */ #define SCORE(m,s) \ -if (m >= 1.0) { \ - if (m == 1.0) \ - score += (16 * s); \ - else if (m == 2.0) \ - score += (4 * s); \ - else if (m < minfrac) \ - score += (1 * s); \ - else if (m < 2.0) \ - score += (3 * s); \ - else \ - score += (2 * s); \ -} else { \ - m = 1/m; \ - if (m < minfrac) \ - score += (1 * s); \ - else \ - score += (2 * s); \ -} +if (m >= 1.0) \ + score += (16 * s) / m; \ +else \ + score += (8 * s) * m; FontEntryPtr -FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep) +FindBestToScale(fpe, entry, vals, best, dxp, dyp, sdxp, sdyp, fpep) FontPathElementPtr fpe; FontEntryPtr entry; FontScalablePtr vals, best; - double *dxp, - *dyp; + double *dxp, *sdxp, + *dyp, *sdyp; FontPathElementPtr *fpep; { FontScalableRec temp; int source, i; int best_score, score; - double dx, dx_amount, - dy, dy_amount, - best_dx, best_dx_amount, - best_dy, best_dy_amount, + double dx, sdx, dx_amount, + dy, sdy, dy_amount, + best_dx, best_sdx, best_dx_amount, + best_dy, best_sdy, best_dy_amount, minfrac; FontEntryPtr zero; FontNameRec zeroName; @@ -181,6 +248,11 @@ FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep) FontScalableExtraPtr extra; FontScaledPtr best_scaled; FontPathElementPtr best_fpe; + FontEntryPtr bitmap = NULL; + FontEntryPtr result; + int aliascount = 20; + FontPathElementPtr bitmap_fpe; + FontNameRec xlfdName; /* find the best match */ best_scaled = 0; @@ -191,6 +263,10 @@ FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep) FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO); zeroName.length = strlen (zeroChars); zeroName.ndashes = entry->name.ndashes; + xlfdName.name = vals->xlfdName; + xlfdName.length = strlen(xlfdName.name); + xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length); + restart_bestscale_loop: ; /* * Look through all the registered bitmap sources for * the same zero name as ours; entries along that one @@ -198,6 +274,31 @@ FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep) */ for (source = 0; source < FontFileBitmapSources.count; source++) { + /* There might already be a bitmap that satisfies the request + but didn't have a zero name that was found by the scalable + font matching logic. Keep track if there is. */ + if (bitmap == NULL && vals->xlfdName != NULL) + { + bitmap_fpe = FontFileBitmapSources.fpe[source]; + dir = (FontDirectoryPtr) bitmap_fpe->private; + bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName); + if (bitmap && bitmap->type != FONT_ENTRY_BITMAP) + { + if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0) + { + aliascount--; + xlfdName.name = bitmap->u.alias.resolved; + xlfdName.length = strlen(xlfdName.name); + xlfdName.ndashes = FontFileCountDashes(xlfdName.name, + xlfdName.length); + bitmap = NULL; + goto restart_bestscale_loop; + } + else + bitmap = NULL; + } + } + if (FontFileBitmapSources.fpe[source] == fpe) zero = entry; else @@ -210,15 +311,11 @@ FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep) extra = zero->u.scalable.extra; for (i = 0; i < extra->numScaled; i++) { + FontScalableRec tmpvals; scaled = &extra->scaled[i]; if (!scaled->bitmap) continue; - if ((scaled->vals.pixel <= 0) || (scaled->vals.point <= 0) || - (scaled->vals.x <= 0) || (scaled->vals.y <= 0)) - continue; - ComputeScaleFactors(&scaled->vals, vals, &dx, &dy); - minfrac = (double) (3 * scaled->vals.pixel); - minfrac = (minfrac + 4.0) / minfrac; + ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy); score = 0; dx_amount = dx; dy_amount = dy; @@ -235,30 +332,54 @@ FindBestToScale(fpe, entry, vals, best, dxp, dyp, fpep) best_score = score; best_dx = dx; best_dy = dy; + best_sdx = sdx; + best_sdy = sdy; best_dx_amount = dx_amount; best_dy_amount = dy_amount; } } } - if (!best_scaled) - return NULL; - - *best = best_scaled->vals; - *fpep = best_fpe; - *dxp = best_dx; - *dyp = best_dy; - return best_scaled->bitmap; + if (best_scaled) + { + *best = best_scaled->vals; + *fpep = best_fpe; + *dxp = best_dx; + *dyp = best_dy; + *sdxp = best_sdx; + *sdyp = best_sdy; + result = best_scaled->bitmap; + } + else + result = NULL; + + if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0)) + { + *fpep = bitmap_fpe; + FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE); + ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp); + result = bitmap; + } + + return result; } static int -computeProps(pf, wasStringProp, npf, isStringProp, nprops, xfactor, yfactor) +doround(x) +double x; +{ + return (x >= 0) ? (int)(x + .5) : (int)(x - .5); +} + +static int +computeProps(pf, wasStringProp, npf, isStringProp, nprops, xfactor, yfactor, + sXfactor, sYfactor) FontPropPtr pf; char *wasStringProp; FontPropPtr npf; char *isStringProp; unsigned int nprops; - double xfactor, - yfactor; + double xfactor, sXfactor, + yfactor, sYfactor; { int n; int count; @@ -272,38 +393,57 @@ computeProps(pf, wasStringProp, npf, isStringProp, nprops, xfactor, yfactor) switch (t->type) { case scaledX: - npf->value = xfactor * pf->value; + npf->value = doround(xfactor * (double)pf->value); + npf->name = pf->name; + npf++; + count++; + npf->value = doround(sXfactor * (double)pf->value); + npf->name = rawFontPropTable[t - fontPropTable].atom; + npf++; + count++; + *isStringProp++ = *wasStringProp; + *isStringProp++ = *wasStringProp; break; case scaledY: - npf->value = yfactor * pf->value; + npf->value = doround(yfactor * (double)pf->value); + npf->name = pf->name; + npf++; + count++; + npf->value = doround(sYfactor * (double)pf->value); + npf->name = rawFontPropTable[t - fontPropTable].atom; + npf++; + count++; + *isStringProp++ = *wasStringProp; + *isStringProp++ = *wasStringProp; break; case unscaled: npf->value = pf->value; + npf->name = pf->name; + npf++; + count++; + *isStringProp++ = *wasStringProp; break; - case scaledXoverY: - npf->value = pf->value * (xfactor / yfactor); } - npf->name = pf->name; - npf++; - count++; - *isStringProp++ = *wasStringProp; } return count; } static int -ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, pProps, pIsStringProp) +ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, sdx, sdy, + sWidth, pProps, pIsStringProp) FontInfoPtr sourceFontInfo; /* the font to be scaled */ char *name; /* name of resulting font */ FontScalablePtr vals; - double dx, - dy; /* scale factors in x and y directions */ + double dx, sdx, + dy, sdy; /* scale factors in x and y directions */ + long sWidth; /* 1000-pixel average width */ FontPropPtr *pProps; /* returns properties; preallocated */ char **pIsStringProp; /* return booleans; preallocated */ { int n; char *ptr1, *ptr2; + char *ptr3; FontPropPtr fp; fontProp *fpt; extern int serverGeneration; @@ -314,7 +454,8 @@ ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, pProps, pIsStringPro initFontPropTable(); fontGeneration = serverGeneration; } - nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp); + nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) + + sizeof(rawFontPropTable) / sizeof(fontProp); fp = (FontPropPtr) xalloc(sizeof(FontPropRec) * nProps); *pProps = fp; if (!fp) @@ -332,14 +473,10 @@ ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, pProps, pIsStringPro fp++, fpt++, n--, isStringProp++) { - ptr1 = ptr2 + 1; - if (*ptr1 == '-') - ptr2 = ptr1; - else { - if (n > 1) - ptr2 = index(ptr1 + 1, '-'); - else - ptr2 = index(ptr1 + 1, '\0'); + if (*ptr2) + { + ptr1 = ptr2 + 1; + if (!(ptr2 = index(ptr1, '-'))) ptr2 = index(ptr1, '\0'); } *isStringProp = 0; @@ -348,11 +485,20 @@ ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, pProps, pIsStringPro fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE); *isStringProp = 1; break; + case truncate_atom: + for (ptr3 = ptr1; *ptr3; ptr3++) + if (*ptr3 == '=' || *ptr3 == '-' || + *ptr3 == '+' || *ptr3 == '~') + break; + if (!*ptr3) ptr3 = ptr2; + fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE); + *isStringProp = 1; + break; case pixel_size: - fp->value = vals->pixel; + fp->value = vals->pixel_matrix[3]; break; case point_size: - fp->value = vals->point; + fp->value = doround(vals->point_matrix[3] * 10.0); break; case resolution_x: fp->value = vals->x; @@ -363,36 +509,112 @@ ComputeScaledProperties(sourceFontInfo, name, vals, dx, dy, pProps, pIsStringPro case average_width: fp->value = vals->width; break; + case fontname: + fp->value = MakeAtom(name, strlen(name), TRUE); + *isStringProp = 1; + break; + case raw_ascent: + fp->value = sourceFontInfo->fontAscent * sdy; + break; + case raw_descent: + fp->value = sourceFontInfo->fontDescent * sdy; + break; + case raw_pointsize: + fp->value = (long)(72270.0 / (double)vals->y + .5); + break; + case raw_pixelsize: + fp->value = 1000; + break; + case raw_average_width: + fp->value = sWidth; + break; } fp->name = fpt->atom; } n = NPROPS; - fp->name = fpt->atom; - fp->value = MakeAtom(name, strlen(name), TRUE); - *isStringProp = 1; - isStringProp++; - fp++; - n++; n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp, - fp, isStringProp, - sourceFontInfo->nprops, dx, dy); + fp, isStringProp, sourceFontInfo->nprops, dx, dy, + sdx, sdy); return n; } static void ScaleBitmap(); +static int +compute_xform_matrix(vals, dx, dy, xform, inv_xform, xmult, ymult) + FontScalablePtr vals; + double dx, dy, *inv_xform, *xmult, *ymult; + register double *xform; +{ + double det, sintheta, costheta, tanphi; + double pixel = get_matrix_vertical_component(vals->pixel_matrix); + double pixelset = get_matrix_horizontal_component(vals->pixel_matrix); + + if (pixel < EPS || pixelset < EPS) return 0; + + /* Initialize the transformation matrix to the scaling factors */ + xform[0] = dx / pixelset; + xform[1] = xform[2] = 0.0; + xform[3] = dy / pixel; + +/* Inline matrix multiply -- somewhat ugly to minimize register usage */ +#define MULTIPLY_XFORM(a,b,c,d) \ +{ \ + register double aa = (a), bb = (b), cc = (c), dd = (d); \ + register double temp; \ + temp = aa * xform[0] + cc * xform[1]; \ + aa = aa * xform[2] + cc * xform[3]; \ + xform[1] = bb * xform[0] + dd * xform[1]; \ + xform[3] = bb * xform[2] + dd * xform[3]; \ + xform[0] = temp; \ + xform[2] = aa; \ +} + + /* Rescale the transformation matrix for size of source font */ + MULTIPLY_XFORM(vals->pixel_matrix[0], + vals->pixel_matrix[1], + vals->pixel_matrix[2], + vals->pixel_matrix[3]); + + *xmult = xform[0]; + *ymult = xform[3]; + + + if (inv_xform == NULL) return 1; + + /* Compute the determinant for use in inverting the matrix. */ + det = xform[0] * xform[3] - xform[1] * xform[2]; + + /* If the determinant is tiny or zero, give up */ + if (fabs(det) < EPS) return 0; + + /* Compute the inverse */ + inv_xform[0] = xform[3] / det; + inv_xform[1] = -xform[1] / det; + inv_xform[2] = -xform[2] / det; + inv_xform[3] = xform[0] / det; + + return 1; +} + /* * ScaleFont * returns a pointer to the new scaled font, or NULL (due to AllocError). */ FontPtr -ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) +ScaleFont(opf, widthMult, heightMult, sWidthMult, sHeightMult, vals, + newWidthMult, newHeightMult, sWidth) FontPtr opf; /* originating font */ double widthMult; /* glyphs width scale factor */ double heightMult; /* glyphs height scale factor */ - FontPropPtr props; /* the new properties */ - int propCount; /* count of new properties */ - char *isStringProp; /* booleans per new property */ + double sWidthMult; /* scalable glyphs width scale factor */ + double sHeightMult; /* scalable glyphs height scale factor */ + FontScalablePtr vals; + double *newWidthMult; /* return: X component of glyphs width + scale factor */ + double *newHeightMult; /* return: Y component of glyphs height + scale factor */ + long *sWidth; /* return: average 1000-pixel width */ { FontPtr pf; FontInfoPtr pfi, @@ -402,14 +624,21 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) CharInfoPtr pci, opci; int nchars; /* how many characters in the font */ - int newWidth, - newHeight; char *glyphBytes; unsigned bytestoalloc; int *scratch; - xCharInfo *pink; int i; int glyph; + int firstCol, lastCol, firstRow, lastRow; + double xform[4], inv_xform[4]; + double xmult, ymult; + int totalwidth = 0, totalchars = 0; + int inkindex1, inkindex2; +#define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \ + firstRow - opf->info.firstRow) * \ + (opf->info.lastCol - opf->info.firstCol + 1) + \ + (i)%(lastCol - firstCol + 1) + \ + firstCol - opf->info.firstCol) extern int bitmapGetBitmaps(); extern int bitmapGetExtents(); @@ -417,6 +646,8 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) extern int bitmapGetMetrics(); extern void bitmapUnloadScalable(); + *sWidth = 0; + opfi = &opf->info; glyph = opf->glyph; obitmapFont = (BitmapFontPtr) opf->fontPrivate; @@ -436,17 +667,70 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) pf->get_glyphs = bitmapGetGlyphs; pf->get_metrics = bitmapGetMetrics; pf->unload_font = bitmapUnloadScalable; + pf->unload_glyphs = NULL; pfi = &pf->info; *pfi = *opfi; + /* If charset subsetting specified in vals, determine what our range + needs to be for the output font */ + if (vals->nranges) + { + int i; + + pfi->allExist = 0; + firstCol = 255; + lastCol = 0; + firstRow = 255; + lastRow = 0; + + for (i = 0; i < vals->nranges; i++) + { + if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high) + { + firstCol = opfi->firstCol; + lastCol = opfi->lastCol; + } + if (firstCol > vals->ranges[i].min_char_low) + firstCol = vals->ranges[i].min_char_low; + if (lastCol < vals->ranges[i].max_char_low) + lastCol = vals->ranges[i].max_char_low; + if (firstRow > vals->ranges[i].min_char_high) + firstRow = vals->ranges[i].min_char_high; + if (lastRow < vals->ranges[i].max_char_high) + lastRow = vals->ranges[i].max_char_high; + } + + if (firstCol > lastCol || firstRow > lastRow) + goto bail; + + if (firstCol < opfi->firstCol) + firstCol = opfi->firstCol; + if (lastCol > opfi->lastCol) + lastCol = opfi->lastCol; + if (firstRow < opfi->firstRow) + firstRow = opfi->firstRow; + if (lastRow > opfi->lastRow) + lastRow = opfi->lastRow; + } + else + { + firstCol = opfi->firstCol; + lastCol = opfi->lastCol; + firstRow = opfi->firstRow; + lastRow = opfi->lastRow; + } + bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec)); if (!bitmapFont) goto bail; - nchars = (opf->info.lastRow - opf->info.firstRow + 1) * - (opf->info.lastCol - opf->info.firstCol + 1); + nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); + pfi->firstRow = firstRow; + pfi->lastRow = lastRow; + pfi->firstCol = firstCol; + pfi->lastCol = lastCol; pf->fontPrivate = (pointer) bitmapFont; bitmapFont->version_num = obitmapFont->version_num; - bitmapFont->num_chars = obitmapFont->num_chars; + bitmapFont->num_chars = nchars; bitmapFont->num_tables = obitmapFont->num_tables; bitmapFont->metrics = 0; bitmapFont->ink_metrics = 0; @@ -457,13 +741,6 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) bitmapFont->metrics = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec)); if (!bitmapFont->metrics) goto bail; - if (obitmapFont->pDefault) - bitmapFont->pDefault = bitmapFont->metrics + (obitmapFont->pDefault - obitmapFont->metrics); - if (obitmapFont->ink_metrics) { - bitmapFont->ink_metrics = (xCharInfo *) xalloc(nchars * sizeof(xCharInfo)); - if (!bitmapFont->ink_metrics) - goto bail; - } bitmapFont->encoding = (CharInfoPtr *) xalloc(nchars * sizeof(CharInfoPtr)); if (!bitmapFont->encoding) goto bail; @@ -476,58 +753,119 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) pfi->anamorphic = FALSE; if (heightMult != widthMult) pfi->anamorphic = TRUE; + pfi->cachable = TRUE; - newHeight = (opfi->fontAscent + opfi->fontDescent) * heightMult; - pfi->fontAscent = opfi->fontAscent * heightMult; - pfi->fontDescent = newHeight - pfi->fontAscent; + if (!compute_xform_matrix(vals, widthMult, heightMult, xform, + inv_xform, &xmult, &ymult)) + goto bail; + + pfi->fontAscent = opfi->fontAscent * ymult; + pfi->fontDescent = opfi->fontDescent * ymult; pfi->minbounds.leftSideBearing = MAXSHORT; pfi->minbounds.rightSideBearing = MAXSHORT; pfi->minbounds.ascent = MAXSHORT; pfi->minbounds.descent = MAXSHORT; pfi->minbounds.characterWidth = MAXSHORT; + pfi->minbounds.attributes = MAXSHORT; pfi->maxbounds.leftSideBearing = MINSHORT; pfi->maxbounds.rightSideBearing = MINSHORT; pfi->maxbounds.ascent = MINSHORT; pfi->maxbounds.descent = MINSHORT; pfi->maxbounds.characterWidth = MINSHORT; + pfi->maxbounds.attributes = MINSHORT; + + /* Compute the transformation and inverse transformation matrices. + Can fail if the determinant is zero. */ + inkindex1 = 0; pci = bitmapFont->metrics; for (i = 0; i < nchars; i++) { - if (opci = obitmapFont->encoding[i]) + if (opci = obitmapFont->encoding[inkindex2 = OLDINDEX(i)]) { + double newlsb, newrsb, newdesc, newasc, point[2]; + +#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) +#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) + + if (vals->nranges) + { + int row = i / (lastCol - firstCol + 1) + firstRow; + int col = i % (lastCol - firstCol + 1) + firstCol; + int ch = (row << 8) + col; + int j; + for (j = 0; j < vals->nranges; j++) + if (ch >= minchar(vals->ranges[j]) && + ch <= maxchar(vals->ranges[j])) + break; + if (j == vals->nranges) + { + bitmapFont->encoding[i] = 0; + continue; + } + } + + if (opci->metrics.leftSideBearing == 0 && + opci->metrics.rightSideBearing == 0 && + opci->metrics.ascent == 0 && + opci->metrics.descent == 0 && + opci->metrics.characterWidth == 0) + { + bitmapFont->encoding[i] = 0; + continue; + } + bitmapFont->encoding[i] = pci; - newWidth = GLYPHWIDTHPIXELS(opci) * widthMult; - newHeight = GLYPHHEIGHTPIXELS(opci) * heightMult; - if (newHeight == 0) - newHeight = 1; - if (newWidth == 0) - newWidth = 1; - - pci->metrics.leftSideBearing = (opci->metrics.leftSideBearing * - widthMult); - pci->metrics.rightSideBearing = newWidth + - pci->metrics.leftSideBearing; - pci->metrics.ascent = opci->metrics.ascent * heightMult; - pci->metrics.descent = newHeight - pci->metrics.ascent; - pci->metrics.characterWidth = opci->metrics.characterWidth * widthMult; - pci->metrics.attributes = opci->metrics.attributes; + + /* Compute new extents for this glyph */ + TRANSFORM_POINT(xform, + opci->metrics.leftSideBearing, + -opci->metrics.descent, + point); + newlsb = point[0]; + newrsb = newlsb; + newdesc = -point[1]; + newasc = -newdesc; + TRANSFORM_POINT(xform, + opci->metrics.leftSideBearing, + opci->metrics.ascent, + point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + TRANSFORM_POINT(xform, + opci->metrics.rightSideBearing, + -opci->metrics.descent, + point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + TRANSFORM_POINT(xform, + opci->metrics.rightSideBearing, + opci->metrics.ascent, + point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + + pci->metrics.leftSideBearing = (int)floor(newlsb); + pci->metrics.rightSideBearing = (int)floor(newrsb + .5); + pci->metrics.descent = (int)ceil(newdesc); + pci->metrics.ascent = (int)floor(newasc + .5); + pci->metrics.characterWidth = + doround((double)opci->metrics.characterWidth * xmult); + pci->metrics.attributes = + doround((double)opci->metrics.characterWidth * sWidthMult); + if (!pci->metrics.characterWidth) + { + /* Since transformation may shrink width, height, and + escapement to zero, make sure existing characters + are not mistaken for undefined characters. */ + + if (pci->metrics.rightSideBearing == + pci->metrics.leftSideBearing) + pci->metrics.rightSideBearing++; + if (pci->metrics.ascent == -pci->metrics.descent) + pci->metrics.ascent++; + } bytestoalloc += BYTES_FOR_GLYPH(pci, glyph); -#define MINMAX(field) \ - if (pfi->minbounds.field > pci->metrics.field) \ - pfi->minbounds.field = pci->metrics.field; \ - if (pfi->maxbounds.field < pci->metrics.field) \ - pfi->maxbounds.field = pci->metrics.field - - MINMAX(leftSideBearing); - MINMAX(rightSideBearing); - MINMAX(ascent); - MINMAX(descent); - MINMAX(characterWidth); -#undef MINMAX pci++; } else @@ -538,11 +876,6 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) goto bail; bzero(bitmapFont->bitmaps, bytestoalloc); - /* Copy over the scaled XLFD properties */ - - pfi->props = props; - pfi->nprops = propCount; - pfi->isStringProp = isStringProp; /* * For each character, set the per-character metrics, scale the glyph, and @@ -551,74 +884,57 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) glyphBytes = bitmapFont->bitmaps; pci = bitmapFont->metrics; - if (widthMult == 1 && heightMult == 1) + for (i = 0; i < nchars; i++) { - for (i = 0; i < nchars; i++) + CharInfoRec temppci; + if ((pci = bitmapFont->encoding[i]) && + (opci = obitmapFont->encoding[OLDINDEX(i)])) { - if (opci = obitmapFont->encoding[i]) - { - int size; - xCharInfo *opink; - - pci = bitmapFont->encoding[i]; - if (pink = bitmapFont->ink_metrics) - { - pink = pink + (pci - bitmapFont->metrics); - opink = obitmapFont->ink_metrics; - opink = opink + (opci - obitmapFont->metrics); - *pink = *opink; - } - pci->bits = glyphBytes; - size = BYTES_FOR_GLYPH(pci, glyph); - bcopy (opci->bits, pci->bits, size); - glyphBytes += size; - } + pci = bitmapFont->encoding[i]; + pci->bits = glyphBytes; + ScaleBitmap (pf, opci, pci, inv_xform, + widthMult, heightMult); + totalchars++; + totalwidth += abs(pci->metrics.characterWidth); + *sWidth += abs((int)(INT16)pci->metrics.attributes); + glyphBytes += BYTES_FOR_GLYPH(pci, glyph); +#define MINMAX(field) \ + if (pfi->minbounds.field > pci->metrics.field) \ + pfi->minbounds.field = pci->metrics.field; \ + if (pfi->maxbounds.field < pci->metrics.field) \ + pfi->maxbounds.field = pci->metrics.field + + MINMAX(leftSideBearing); + MINMAX(rightSideBearing); + MINMAX(ascent); + MINMAX(descent); + MINMAX(characterWidth); + + /* Hack: Cast attributes into a signed quantity. Tread lightly + for now and don't go changing the global Xproto.h file */ + if ((INT16)pfi->minbounds.attributes > + (INT16)pci->metrics.attributes) + pfi->minbounds.attributes = pci->metrics.attributes; + if ((INT16)pfi->maxbounds.attributes < + (INT16)pci->metrics.attributes) + pfi->maxbounds.attributes = pci->metrics.attributes; +#undef MINMAX } } + pfi->ink_minbounds = pfi->minbounds; + pfi->ink_maxbounds = pfi->maxbounds; + if (totalchars) + { + int tc2 = totalchars / 2; + vals->width = (totalwidth * 10 + tc2) / totalchars; + *sWidth = (*sWidth * 10 + tc2) / totalchars; + } else { - /* Allocate the scratch space for the glyph scaling routine. */ - scratch = (int *) - xalloc((int) ((opfi->maxbounds.rightSideBearing - - opfi->minbounds.leftSideBearing) - * widthMult * sizeof(int))); - if (!scratch) - goto bail; - - pink = bitmapFont->ink_metrics; - if (pink) { - pfi->ink_minbounds.leftSideBearing = MAXSHORT; - pfi->ink_minbounds.rightSideBearing = MAXSHORT; - pfi->ink_minbounds.ascent = MAXSHORT; - pfi->ink_minbounds.descent = MAXSHORT; - pfi->ink_minbounds.characterWidth = MAXSHORT; - pfi->ink_maxbounds.leftSideBearing = MINSHORT; - pfi->ink_maxbounds.rightSideBearing = MINSHORT; - pfi->ink_maxbounds.ascent = MINSHORT; - pfi->ink_maxbounds.descent = MINSHORT; - pfi->ink_maxbounds.characterWidth = MINSHORT; - } else { - pfi->ink_minbounds = pfi->minbounds; - pfi->ink_maxbounds = pfi->maxbounds; - } - - for (i = 0; i < nchars; i++) - { - if (opci = obitmapFont->encoding[i]) - { - pci = bitmapFont->encoding[i]; - if (pink = bitmapFont->ink_metrics) - { - pink = pink + (pci - bitmapFont->metrics); - } - pci->bits = glyphBytes; - ScaleBitmap (pf, opci, pci, scratch, pink); - glyphBytes += BYTES_FOR_GLYPH(pci, glyph); - } - } - FontComputeInfoAccelerators (pfi); - xfree(scratch); + vals->width = 0; + *sWidth = 0; } + FontComputeInfoAccelerators (pfi); if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) { unsigned int r, @@ -636,6 +952,8 @@ ScaleFont(opf, widthMult, heightMult, props, propCount, isStringProp) } } + *newWidthMult = xmult; + *newHeightMult = ymult; return pf; bail: if (pf) @@ -672,41 +990,39 @@ lcm(a, b) /* least common multiple */ } static void -ScaleBitmap(pFont, opci, pci, scratch, pink) +ScaleBitmap(pFont, opci, pci, inv_xform, widthMult, heightMult) FontPtr pFont; CharInfoPtr opci; CharInfoPtr pci; - int *scratch; - xCharInfo *pink; + double *inv_xform; + double widthMult; + double heightMult; { - char *bitmap, + register char *bitmap, /* The bits */ *newBitmap; - int width, + register int bpr, /* Padding information */ + newBpr; + int width, /* Extents information */ height, newWidth, newHeight; - int kcounter; /* 0 <= kcounter <= k */ - int lcounter; /* 0 <= lcounter <= l */ - int kkcounter; /* 0 <= kkcounter <= kk */ - int llcounter; /* 0 <= llcounter <= ll */ - int newBit; /* newBitmap column index, by bits */ - int *acc; /* pseudonym for scratch */ - int bitValue; /* tmp variable */ - int dataByte; - char *dataBytePointer; - char *saveDataBytePointer; - - /* The following variables have constant values, once assigned. */ - - int virtualWidth; /* unpadded bit width of the virtual bitmap */ - int virtualHeight; /* unpadded bit height of the virtual bitmap */ - int k; /* horizontal bit copies in virtualBitmap */ - int l; /* vertical bit copies in virtualBitmap */ - int kk; /* horiz. virtual bits in a newBitmap bit */ - int ll; /* vertical virtual bits in a newBitmap bit */ - int threshold; - int padWidth; /* actual width in bytes of pad in bitmap */ - int newPadWidth; + int row, /* Loop variables */ + col; + INT32 deltaX, /* Increments for resampling loop */ + deltaY; + INT32 xValue, /* Subscripts for resampling loop */ + yValue; + double point[2]; + unsigned char *char_grayscale = 0; + INT32 *diffusion_workspace, *thisrow, *nextrow, pixmult; + int box_x, box_y; + double dtemp; + + static unsigned char masklsb[] = + { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; + static unsigned char maskmsb[] = + { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb); bitmap = opci->bits; newBitmap = pci->bits; @@ -717,183 +1033,289 @@ ScaleBitmap(pFont, opci, pci, scratch, pink) if (!newWidth || !newHeight || !width || !height) return; - padWidth = BYTES_PER_ROW(width, pFont->glyph) - ((width + 7) >> 3); - newPadWidth = BYTES_PER_ROW(newWidth, pFont->glyph) - ((newWidth + 7) >> 3); - virtualWidth = lcm(width, newWidth); - virtualHeight = lcm(height, newHeight); - k = virtualWidth / width; - l = virtualHeight / height; - kk = virtualWidth / newWidth; - ll = virtualHeight / newHeight; - threshold = kk * ll; - if (pink) { - pink->leftSideBearing = MAXSHORT; - pink->rightSideBearing = MINSHORT; - pink->ascent = MINSHORT; - pink->descent = MINSHORT; - pink->characterWidth = pci->metrics.characterWidth; - pink->attributes = pci->metrics.attributes; + bpr = BYTES_PER_ROW(width, pFont->glyph); + newBpr = BYTES_PER_ROW(newWidth, pFont->glyph); + + if (widthMult > 0.0 && heightMult > 0.0 && + (widthMult < 1.0 || heightMult < 1.0)) + { + /* We are reducing in one or both dimensions. In an attempt to + reduce aliasing, we'll antialias by passing the original + glyph through a low-pass box filter (which results in a + grayscale image), then use error diffusion to create bitonal + output in the resampling loop. */ + + /* First compute the sizes of the box filter */ + widthMult = 1.0 / widthMult; + heightMult = 1.0 / heightMult; + dtemp = widthMult * heightMult; + if (dtemp < 2.0) dtemp = 2.0; + if (dtemp > 256.0) dtemp = 256.0; + pixmult = (INT32)(dtemp * 256.0); + box_x = width / 2; + box_y = height / 2; + widthMult = ceil(widthMult); + heightMult = ceil(heightMult); + if (widthMult < (double)box_x) box_x = (int)widthMult; + if (heightMult < (double)box_y) box_y = (int)heightMult; + + if (box_x > 1 || box_y > 1) + { + /* Looks like we need to anti-alias. Create a workspace to + contain the grayscale character plus an additional row and + column for scratch */ + char_grayscale = + (unsigned char *)xalloc((width + 1) * (height + 1)); + if (char_grayscale) + { + diffusion_workspace = + (INT32 *)xalloc((newWidth + 2) * 2 * sizeof(int)); + if (!diffusion_workspace) + { + xfree(char_grayscale); + char_grayscale = (unsigned char *)0; + } + /* Initialize our error diffusion workspace for later use */ + bzero((char *)diffusion_workspace + sizeof(INT32), + (newWidth + 3) * sizeof(int)); + thisrow = diffusion_workspace + 1; + nextrow = diffusion_workspace + newWidth + 3; + } + } } - saveDataBytePointer = bitmap; - newBitmap--; - lcounter = l; - for (; newHeight; newHeight--, newBitmap += newPadWidth) { - - newBit = newWidth; - acc = scratch; - do - *acc++ = threshold; - while (--newBit); - - llcounter = ll; - while (llcounter) { - int bit; /* index into glyph row, indicating a bit */ - int row_dup;/* row duplication count from source */ - int kdup; - int kkdup; - - if (!lcounter) { - lcounter = l; - dataBytePointer += padWidth; - saveDataBytePointer = dataBytePointer; - } else - dataBytePointer = saveDataBytePointer; - - if ((row_dup = llcounter) > lcounter) - row_dup = lcounter; - lcounter -= row_dup; - llcounter -= row_dup; - row_dup <<= 1; - - bit = 1; - kdup = k * row_dup; - kkdup = kk * row_dup; - kcounter = 0; - newBit = newWidth; - acc = scratch; - do { - int tmp = 0; - - kkcounter = kkdup; - if (!kcounter) { - /* advance to the next column of the source bitmap */ - kcounter = kdup; - if (!(--bit)) { - bit = 8; - dataByte = *dataBytePointer++; - } - /* extract the appropriate bit from source bitmap */ - if (pFont->bit == LSBFirst) { - bitValue = dataByte & 1; - dataByte >>= 1; - } else { - bitValue = dataByte & 128; - dataByte <<= 1; - } + + if (char_grayscale) + { + /* We will be doing antialiasing. First copy the bitmap into + our buffer, mapping input range [0,1] to output range + [0,255]. */ + unsigned char *srcptr, *dstptr; + srcptr = (unsigned char *)bitmap; + dstptr = char_grayscale; + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0; + srcptr += bpr; /* On to next row of source */ + dstptr++; /* Skip scratch column in dest */ + } + if (box_x > 1) + { + /* Our box filter has a width > 1... let's filter the rows */ + + int right_width = box_x / 2; + int left_width = box_x - right_width - 1; + + for (row = 0; row < height; row++) + { + int sum = 0; + int left_size = 0, right_size = 0; + + srcptr = char_grayscale + (width + 1) * row; + dstptr = char_grayscale + (width + 1) * height; /* scratch */ + + /* We've computed the shape of our full box filter. Now + compute the right-hand part of the moving sum */ + for (right_size = 0; right_size < right_width; right_size++) + sum += srcptr[right_size]; + + /* Now start moving the sum, growing the box filter, and + dropping averages into our scratch buffer */ + for (left_size = 0; left_size < left_width; left_size++) + { + sum += srcptr[right_width]; + *dstptr++ = sum / (left_size + right_width + 1); + srcptr++; } - while ((kkcounter -= kcounter) > 0) { - if (bitValue) - tmp += kcounter; - /* advance to the next column of the source bitmap */ - kcounter = kdup; - if (!(--bit)) { - bit = 8; - dataByte = *dataBytePointer++; - } - /* extract the appropriate bit from source bitmap */ - if (pFont->bit == LSBFirst) { - bitValue = dataByte & 1; - dataByte >>= 1; - } else { - bitValue = dataByte & 128; - dataByte <<= 1; - } + + /* The box filter has reached full width... continue + computation of moving average until the right side + hits the wall. */ + for (col = left_size; col + right_size < width; col++) + { + sum += srcptr[right_width]; + *dstptr++ = sum / box_x; + sum -= srcptr[-left_width]; + srcptr++; + } + + /* Collapse the right side of the box filter */ + for (; right_size > 0; right_size--) + { + *dstptr++ = sum / (left_width + right_size); + sum -= srcptr[-left_width]; + srcptr++; } - if (bitValue) - tmp += kcounter + kkcounter; - kcounter = -kkcounter; - *acc++ -= tmp; + + /* Done with the row... copy dest back over source */ + bcopy(char_grayscale + (width + 1) * height, + char_grayscale + (width + 1) * row, width); } - while (--newBit); } - /* - * Set the appropriate bits in newBitmap, based on the count of bits - * set in the virtual bitmap which map to a single bit in the new - * bitmap, and based on the knowing the constant number of bits in the - * virtual bitmap which map to a bit in the new bitmap. - */ - acc = scratch; - - if (pFont->bit == LSBFirst) - bitValue = 128; - else - bitValue = 1; - newBit = newWidth; - do { - if (pFont->bit == LSBFirst) { - if ((bitValue <<= 1) == 256) { - bitValue = 0x1; - newBitmap++; + if (box_y > 1) + { + /* Our box filter has a height > 1... let's filter the columns */ + + int bottom_height = box_y / 2; + int top_height = box_y - bottom_height - 1; + + for (col = 0; col < width; col++) + { + int sum = 0; + int top_size = 0, bottom_size = 0; + + srcptr = char_grayscale + col; + dstptr = char_grayscale + width; /* scratch */ + + /* We've computed the shape of our full box filter. Now + compute the bottom part of the moving sum */ + for (bottom_size = 0; + bottom_size < bottom_height; + bottom_size++) + sum += srcptr[bottom_size * (width + 1)]; + + /* Now start moving the sum, growing the box filter, and + dropping averages into our scratch buffer */ + for (top_size = 0; top_size < top_height; top_size++) + { + sum += srcptr[bottom_height * (width + 1)]; + *dstptr = sum / (top_size + bottom_height + 1); + dstptr += width + 1; + srcptr += width + 1; + } + + /* The box filter has reached full height... continue + computation of moving average until the bottom + hits the wall. */ + for (row = top_size; row + bottom_size < height; row++) + { + sum += srcptr[bottom_height * (width + 1)]; + *dstptr = sum / box_y; + dstptr += width + 1; + sum -= srcptr[-top_height * (width + 1)]; + srcptr += width + 1; } - } else { - if (!(bitValue >>= 1)) { - bitValue = 128; - newBitmap++; + + /* Collapse the bottom of the box filter */ + for (; bottom_size > 0; bottom_size--) + { + *dstptr = sum / (top_height + bottom_size); + dstptr += width + 1; + sum -= srcptr[-top_height * (width + 1)]; + srcptr += width + 1; + } + + /* Done with the column... copy dest back over source */ + + dstptr = char_grayscale + col; + srcptr = char_grayscale + width; /* scratch */ + for (row = 0; row < height; row++) + { + *dstptr = *srcptr; + dstptr += width + 1; + srcptr += width + 1; } } - if (*acc++ < 0) - *newBitmap |= bitValue; - } while (--newBit); - if (pink) { - for (acc = scratch, newBit = newWidth; - --newBit >= 0 && *acc++ >= 0; - ); - if (newBit >= 0) { - if (newHeight >= pink->ascent) - pink->ascent = newHeight; - pink->descent = newHeight; - newBit = pci->metrics.leftSideBearing + newWidth - newBit - 1; - if (newBit < pink->leftSideBearing) - pink->leftSideBearing = newBit; + } + } + + /* Compute the increment values for the resampling loop */ + TRANSFORM_POINT(inv_xform, 1, 0, point); + deltaX = (INT32)(point[0] * 65536.0); + deltaY = (INT32)(-point[1] * 65536.0); + + /* Resampling loop: resamples original glyph for generation of new + glyph in transformed coordinate system. */ + + for (row = 0; row < newHeight; row++) + { + /* Compute inverse transformation for start of this row */ + TRANSFORM_POINT(inv_xform, + (double)(pci->metrics.leftSideBearing) + .5, + (double)(pci->metrics.ascent - row) - .5, + point); + + /* Adjust for coordinate system to get resampling point */ + point[0] -= opci->metrics.leftSideBearing; + point[1] = opci->metrics.ascent - point[1]; + + /* Convert to integer coordinates */ + xValue = (INT32)(point[0] * 65536.0); + yValue = (INT32)(point[1] * 65536.0); + + if (char_grayscale) + { + INT32 *temp; + for (col = 0; col < newWidth; col++) + { + register int x = xValue >> 16, y = yValue >> 16; + int pixvalue, error; + + pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ? + char_grayscale[x + y * (width + 1)] : 0) + + thisrow[col] / 16; + + /* Capricious and arbitrary tweaking of grayvalue to + increase ink a bit */ + pixvalue = pixvalue * pixmult / 256; + if (pixvalue > 255) pixvalue = 255; + else if (pixvalue < 0) pixvalue = 0; + + /* Choose the bit value and set resulting error value */ + if (pixvalue >= 128) + { + newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; + error = pixvalue - 255; + } + else + error = -pixvalue; + + /* Diffuse the error */ + thisrow[col + 1] += error * 7; + nextrow[col - 1] += error * 3; + nextrow[col] += error * 5; + nextrow[col + 1] = error; + + xValue += deltaX; + yValue += deltaY; } - for (acc = scratch + newWidth, newBit = newWidth; - --newBit >= 0 && *--acc >= 0; - ); - if (newBit >= 0) + + /* Add in error values that fell off either end */ + nextrow[0] += nextrow[-1]; + nextrow[newWidth - 2] += thisrow[newWidth]; + nextrow[newWidth - 1] += nextrow[newWidth]; + nextrow[newWidth] = 0; + + temp = nextrow; + nextrow = thisrow; + thisrow = temp; + nextrow[-1] = nextrow[0] = 0; + } + else + { + for (col = 0; col < newWidth; col++) { - newBit = pci->metrics.leftSideBearing + newBit + 1; - if (newBit > pink->rightSideBearing) - pink->rightSideBearing = newBit; + register int x = xValue >> 16, y = yValue >> 16; + + if (x >= 0 && x < width && y >= 0 && y < height) + { + /* Use point-sampling for rescaling. */ + + if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7]) + newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; + } + + xValue += deltaX; + yValue += deltaY; } } } -#define MINMAX(field) \ - if (pFont->info.ink_minbounds.field > pink->field) \ - pFont->info.ink_minbounds.field = pink->field; \ - if (pFont->info.ink_maxbounds.field < pink->field) \ - pFont->info.ink_maxbounds.field = pink->field - if (pink) { - if (pink->ascent == MINSHORT) - { - /* hack to make computation below work */ - pink->ascent = pci->metrics.descent; - /* these would also have not been set as this character is empty */ - pink->descent = pink->ascent + 1; - pink->leftSideBearing = 0; - pink->rightSideBearing = 0; - } - height = pink->ascent - pink->descent + 1; - pink->ascent = pci->metrics.ascent - - (GLYPHHEIGHTPIXELS(pci) - pink->ascent); - pink->descent = height - pink->ascent; - MINMAX(leftSideBearing); - MINMAX(rightSideBearing); - MINMAX(ascent); - MINMAX(descent); - MINMAX(characterWidth); + if (char_grayscale) + { + xfree(char_grayscale); + xfree(diffusion_workspace); } -#undef MINMAX } #ifdef NOTDEF @@ -953,12 +1375,13 @@ BitmapOpenScalable (fpe, pFont, flags, entry, fileName, vals, format, fmask) { FontScalableRec best; FontPtr font = NullFont; - double dx, - dy; + double dx, sdx, + dy, sdy; FontPropPtr props; char *isStringProp; int propCount; int status; + long sWidth; FontEntryPtr scaleFrom; FontPathElementPtr scaleFPE; @@ -973,11 +1396,13 @@ BitmapOpenScalable (fpe, pFont, flags, entry, fileName, vals, format, fmask) return NullFontFileName; #endif - scaleFrom = FindBestToScale (fpe, entry, vals, &best, &dx, &dy, &scaleFPE); + scaleFrom = FindBestToScale (fpe, entry, vals, &best, &dx, &dy, + &sdx, &sdy, &scaleFPE); if (!scaleFrom) return BadFontName; - status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, format, fmask); + status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, + format, fmask); if (status != Successful) return BadFontName; @@ -985,48 +1410,46 @@ BitmapOpenScalable (fpe, pFont, flags, entry, fileName, vals, format, fmask) if (!vals->width) vals->width = best.width * dx; - /* Prepare font properties for the new font */ - - strcpy (fontName, scaleFrom->name.name); - FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE); + /* Compute the scaled font */ - propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, dx, dy, - &props, &isStringProp); + font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth); - if (propCount && (!props || !isStringProp)) + if (!font) + { + if (!sourceFont->refcnt) + FontFileCloseFont((FontPathElementPtr) 0, sourceFont); return AllocError; - - /* Compute the scaled font */ + } - font = ScaleFont(sourceFont, dx, dy, props, propCount, isStringProp); + /* Prepare font properties for the new font */ + + strcpy (fontName, scaleFrom->name.name); + FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE); - /* Dispose source font */ + propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, + dx, dy, sdx, sdy, sWidth, &props, + &isStringProp); if (!sourceFont->refcnt) FontFileCloseFont((FontPathElementPtr) 0, sourceFont); - if (!font) + if (propCount && (!props || !isStringProp)) { - xfree (props); - xfree (isStringProp); + font->info.nprops = 0; + font->info.props = (FontPropPtr)0; + font->info.isStringProp = (char *)0; + bitmapUnloadScalable(font); return AllocError; } + + font->info.props = props; + font->info.nprops = propCount; + font->info.isStringProp = isStringProp; + *pFont = font; return Successful; } -static -ScaleBounds (bounds, dx, dy) - xCharInfo *bounds; - double dx, dy; -{ - bounds->leftSideBearing *= dx; - bounds->rightSideBearing *= dx; - bounds->ascent *= dy; - bounds->descent *= dy; - bounds->characterWidth *= dx; -} - BitmapGetInfoScalable (fpe, pFontInfo, entry, fontName, fileName, vals) FontPathElementPtr fpe; FontInfoPtr pFontInfo; @@ -1035,44 +1458,22 @@ BitmapGetInfoScalable (fpe, pFontInfo, entry, fontName, fileName, vals) char *fileName; FontScalablePtr vals; { - FontEntryPtr scaleFrom; - FontPathElementPtr scaleFPE; - double dx, - dy; - FontScalableRec best; - FontInfoRec scaleInfo; - int ret; - int propCount; - FontPropPtr props; - char *isStringProp; - - scaleFrom = FindBestToScale (fpe, entry, vals, &best, &dx, &dy, &scaleFPE); - if (!scaleFrom) - return BadFontName; - ret = FontFileGetInfoBitmap (fpe, &scaleInfo, scaleFrom); + FontPtr pfont; + int flags = 0; + long format = 0; /* It doesn't matter what format for just info */ + long fmask = 0; + int ret; + + ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals, + format, fmask); if (ret != Successful) - return ret; + return ret; + *pFontInfo = pfont->info; - if (!vals->width) - vals->width = best.width * dx; - - propCount = ComputeScaledProperties (&scaleInfo, fontName->name, vals, dx, dy, - &props, &isStringProp); - xfree (scaleInfo.isStringProp); - xfree (scaleInfo.props); - if (propCount && (!props || !isStringProp)) - return AllocError; + pfont->info.props = NULL; + pfont->info.isStringProp = NULL; - *pFontInfo = scaleInfo; - pFontInfo->props = props; - pFontInfo->isStringProp = isStringProp; - pFontInfo->nprops = propCount; - pFontInfo->fontDescent *= dy; - pFontInfo->fontAscent *= dy; - ScaleBounds (&pFontInfo->minbounds, dx, dy); - ScaleBounds (&pFontInfo->maxbounds, dx, dy); - ScaleBounds (&pFontInfo->ink_minbounds, dx, dy); - ScaleBounds (&pFontInfo->ink_minbounds, dx, dy); + (*pfont->unload_font)(pfont); return Successful; } diff --git a/xc/lib/font/bitmap/pcfread.c b/xc/lib/font/bitmap/pcfread.c index 903059501..15c028ab9 100644 --- a/xc/lib/font/bitmap/pcfread.c +++ b/xc/lib/font/bitmap/pcfread.c @@ -1,5 +1,5 @@ /* - * $XConsortium: pcfread.c,v 1.10 92/05/12 18:07:47 gildea Exp $ + * $XConsortium: pcfread.c,v 1.11 92/05/29 17:10:17 gildea Exp $ * * Copyright 1990 Massachusetts Institute of Technology * @@ -309,6 +309,7 @@ pcfGetAccel(pFontInfo, file, tables, ntables, type) pFontInfo->inkMetrics = pcfGetINT8(file, format); pFontInfo->drawDirection = pcfGetINT8(file, format); pFontInfo->anamorphic = FALSE; + pFontInfo->cachable = TRUE; /* natural alignment */ pcfGetINT8(file, format); pFontInfo->fontAscent = pcfGetINT32(file, format); pFontInfo->fontDescent = pcfGetINT32(file, format); @@ -562,6 +563,7 @@ pcfReadFont(pFont, file, bit, byte, glyph, scan) pFont->get_glyphs = bitmapGetGlyphs; pFont->get_metrics = bitmapGetMetrics; pFont->unload_font = pcfUnloadFont; + pFont->unload_glyphs = NULL; pFont->bit = bit; pFont->byte = byte; pFont->glyph = glyph; diff --git a/xc/lib/font/bitmap/snfread.c b/xc/lib/font/bitmap/snfread.c index 3146c93cd..240c802c7 100644 --- a/xc/lib/font/bitmap/snfread.c +++ b/xc/lib/font/bitmap/snfread.c @@ -22,7 +22,7 @@ SOFTWARE. ************************************************************************/ -/* $XConsortium: snfread.c,v 1.11 92/05/12 18:07:49 gildea Exp $ */ +/* $XConsortium: snfread.c,v 1.12 92/05/29 17:10:19 gildea Exp $ */ #include <ctype.h> #include "fontfilest.h" @@ -88,6 +88,7 @@ snfCopyInfo(snfInfo, pFontInfo) pFontInfo->allExist = snfInfo->allExist; pFontInfo->drawDirection = snfInfo->drawDirection; pFontInfo->anamorphic = FALSE; + pFontInfo->cachable = TRUE; pFontInfo->maxOverlap = 0; pFontInfo->minbounds = snfInfo->minbounds.metrics; pFontInfo->maxbounds = snfInfo->maxbounds.metrics; @@ -252,6 +253,7 @@ snfReadFont(pFont, file, bit, byte, glyph, scan) } if (ret != Successful) { + xfree(bitmaps); xfree(fontspace); return ret; } @@ -360,6 +362,7 @@ snfReadFont(pFont, file, bit, byte, glyph, scan) pFont->get_glyphs = bitmapGetGlyphs; pFont->get_metrics = bitmapGetMetrics; pFont->unload_font = snfUnloadFont; + pFont->unload_glyphs = NULL; pFont->bit = bit; pFont->byte = byte; pFont->glyph = glyph; |