aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/font/bitmap/bitscale.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/font/bitmap/bitscale.c')
-rw-r--r--nx-X11/lib/font/bitmap/bitscale.c1978
1 files changed, 0 insertions, 1978 deletions
diff --git a/nx-X11/lib/font/bitmap/bitscale.c b/nx-X11/lib/font/bitmap/bitscale.c
deleted file mode 100644
index 8f7247eaf..000000000
--- a/nx-X11/lib/font/bitmap/bitscale.c
+++ /dev/null
@@ -1,1978 +0,0 @@
-/* $Xorg: bitscale.c,v 1.5 2001/02/09 02:04:02 xorgcvs Exp $ */
-/*
-
-Copyright 1991, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-/* $XFree86: xc/lib/font/bitmap/bitscale.c,v 3.29tsi Exp $ */
-
-/*
- * Author: Keith Packard, MIT X Consortium
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-/*
- * Translate monolithic #defines to modular definitions
- */
-
-#ifdef PCFFORMAT
-#define XFONT_PCFFORMAT 1
-#endif
-
-#ifdef SNFFORMAT
-#define XFONT_SNFFORMAT 1
-#endif
-
-#ifdef BDFFORMAT
-#define XFONT_BDFFORMAT 1
-#endif
-
-#include <X11/fonts/fntfilst.h>
-#include <X11/fonts/bitmap.h>
-#include <X11/fonts/fontutil.h>
-#ifndef FONTMODULE
-#ifdef _XOPEN_SOURCE
-#include <math.h>
-#else
-#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
-#include <math.h>
-#undef _XOPEN_SOURCE
-#endif
-#endif
-
-#ifndef MAX
-#define MAX(a,b) (((a)>(b)) ? a : b)
-#endif
-
-/* Should get this from elsewhere */
-extern unsigned long serverGeneration;
-
-static void bitmapUnloadScalable (FontPtr pFont);
-static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci,
- CharInfoPtr pci, double *inv_xform,
- double widthMult, double heightMult );
-static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf,
- double widthMult, double heightMult,
- FontScalablePtr vals);
-static FontPtr PrinterScaleBitmaps(FontPtr pf, FontPtr opf,
- double widthMult, double heightMult,
- FontScalablePtr vals);
-
-enum scaleType {
- 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 {
- char *name;
- Atom atom;
- enum scaleType type;
-} fontProp;
-
-typedef FontPtr (*ScaleFunc) ( FontPtr /* pf */,
- FontPtr /* opf */,
- double /* widthMult */,
- double /* heightMult */,
- FontScalablePtr /* vals */);
-
-/* These next two arrays must be kept in step with the renderer array */
-ScaleFunc scale[] =
-{
-#if XFONT_PCFFORMAT
- BitmapScaleBitmaps,
- BitmapScaleBitmaps,
-#ifdef X_GZIP_FONT_COMPRESSION
- BitmapScaleBitmaps,
-#endif
-#endif
-#if XFONT_SNFFORMAT
- BitmapScaleBitmaps,
- BitmapScaleBitmaps,
-#ifdef X_GZIP_FONT_COMPRESSION
- BitmapScaleBitmaps,
-#endif
-#endif
-#if XFONT_BDFFORMAT
- BitmapScaleBitmaps,
- BitmapScaleBitmaps,
-#ifdef X_GZIP_FONT_COMPRESSION
- BitmapScaleBitmaps,
-#endif
-#endif
-#if XFONT_PCFFORMAT
- PrinterScaleBitmaps,
-#endif
-};
-
-static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe,
- FontEntryPtr entry,
- FontScalablePtr vals,
- FontScalablePtr best,
- double *dxp, double *dyp,
- double *sdxp, double *sdyp,
- FontPathElementPtr *fpep );
-static FontEntryPtr FindPmfToScale ( FontPathElementPtr fpe,
- FontEntryPtr entry,
- FontScalablePtr vals,
- FontScalablePtr best,
- double *dxp, double *dyp,
- double *sdxp, double *sdyp,
- FontPathElementPtr *fpep );
-
-typedef FontEntryPtr (*FindToScale) (FontPathElementPtr fpe,
- FontEntryPtr entry,
- FontScalablePtr vals,
- FontScalablePtr best,
- double *dxp, double *dyp,
- double *sdxp, double *sdyp,
- FontPathElementPtr *fpep);
-FindToScale find_scale[] =
-{
-#if XFONT_PCFFORMAT
- FindBestToScale,
- FindBestToScale,
-#ifdef X_GZIP_FONT_COMPRESSION
- FindBestToScale,
-#endif
-#endif
-#if XFONT_SNFFORMAT
- FindBestToScale,
- FindBestToScale,
-#ifdef X_GZIP_FONT_COMPRESSION
- FindBestToScale,
-#endif
-#endif
-#if XFONT_BDFFORMAT
- FindBestToScale,
- FindBestToScale,
-#ifdef X_GZIP_FONT_COMPRESSION
- FindBestToScale,
-#endif
-#endif
-#if XFONT_PCFFORMAT
- FindPmfToScale,
-#endif
-};
-
-static unsigned long bitscaleGeneration = 0; /* initialization flag */
-
-static fontProp fontNamePropTable[] = {
- { "FOUNDRY", 0, atom },
- { "FAMILY_NAME", 0, atom },
- { "WEIGHT_NAME", 0, atom },
- { "SLANT", 0, atom },
- { "SETWIDTH_NAME", 0, atom },
- { "ADD_STYLE_NAME", 0, atom },
- { "PIXEL_SIZE", 0, pixel_size },
- { "POINT_SIZE", 0, point_size },
- { "RESOLUTION_X", 0, resolution_x },
- { "RESOLUTION_Y", 0, resolution_y },
- { "SPACING", 0, atom },
- { "AVERAGE_WIDTH", 0, average_width },
- { "CHARSET_REGISTRY", 0, atom },
- { "CHARSET_ENCODING", 0, truncate_atom },
- { "FONT", 0, fontname },
- { "RAW_ASCENT", 0, raw_ascent },
- { "RAW_DESCENT", 0, raw_descent },
- { "RAW_PIXEL_SIZE", 0, raw_pixelsize },
- { "RAW_POINT_SIZE", 0, raw_pointsize },
- { "RAW_AVERAGE_WIDTH", 0, raw_average_width }
-};
-
-#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 },
- { "NORM_SPACE", 0, scaledX },
- { "MAX_SPACE", 0, scaledX },
- { "END_SPACE", 0, scaledX },
- { "AVG_CAPITAL_WIDTH", 0, scaledX },
- { "AVG_LOWERCASE_WIDTH", 0, scaledX },
- { "QUAD_WIDTH", 0, scaledX },
- { "FIGURE_WIDTH", 0, scaledX },
- { "SUPERSCRIPT_X", 0, scaledX },
- { "SUPERSCRIPT_Y", 0, scaledY },
- { "SUBSCRIPT_X", 0, scaledX },
- { "SUBSCRIPT_Y", 0, scaledY },
- { "SUPERSCRIPT_SIZE", 0, scaledY },
- { "SUBSCRIPT_SIZE", 0, scaledY },
- { "SMALL_CAP_SIZE", 0, scaledY },
- { "UNDERLINE_POSITION", 0, scaledY },
- { "UNDERLINE_THICKNESS", 0, scaledY },
- { "STRIKEOUT_ASCENT", 0, scaledY },
- { "STRIKEOUT_DESCENT", 0, scaledY },
- { "CAP_HEIGHT", 0, scaledY },
- { "X_HEIGHT", 0, scaledY },
- { "ITALIC_ANGLE", 0, unscaled },
- { "RELATIVE_SETWIDTH", 0, unscaled },
- { "RELATIVE_WEIGHT", 0, unscaled },
- { "WEIGHT", 0, unscaled },
- { "DESTINATION", 0, unscaled },
- { "PCL_FONT_NAME", 0, unscaled },
- { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled }
-};
-
-/* sleazy way to shut up the compiler */
-#define zerohack (enum scaleType)0
-
-static fontProp rawFontPropTable[] = {
- { "RAW_MIN_SPACE", 0, },
- { "RAW_NORM_SPACE", 0, },
- { "RAW_MAX_SPACE", 0, },
- { "RAW_END_SPACE", 0, },
- { "RAW_AVG_CAPITAL_WIDTH", 0, },
- { "RAW_AVG_LOWERCASE_WIDTH", 0, },
- { "RAW_QUAD_WIDTH", 0, },
- { "RAW_FIGURE_WIDTH", 0, },
- { "RAW_SUPERSCRIPT_X", 0, },
- { "RAW_SUPERSCRIPT_Y", 0, },
- { "RAW_SUBSCRIPT_X", 0, },
- { "RAW_SUBSCRIPT_Y", 0, },
- { "RAW_SUPERSCRIPT_SIZE", 0, },
- { "RAW_SUBSCRIPT_SIZE", 0, },
- { "RAW_SMALL_CAP_SIZE", 0, },
- { "RAW_UNDERLINE_POSITION", 0, },
- { "RAW_UNDERLINE_THICKNESS", 0, },
- { "RAW_STRIKEOUT_ASCENT", 0, },
- { "RAW_STRIKEOUT_DESCENT", 0, },
- { "RAW_CAP_HEIGHT", 0, },
- { "RAW_X_HEIGHT", 0, }
-};
-
-static void
-initFontPropTable(void)
-{
- int i;
- fontProp *t;
-
- i = sizeof(fontNamePropTable) / sizeof(fontProp);
- for (t = fontNamePropTable; i; i--, t++)
- t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
-
- 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);
-}
-
-#if 0
-static FontEntryPtr
-GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name)
-{
- FontDirectoryPtr dir;
-
- dir = (FontDirectoryPtr) fpe->private;
- return FontFileFindNameInDir (&dir->scalable, name);
-}
-#endif
-
-static double
-get_matrix_horizontal_component(double *matrix)
-{
- return hypot(matrix[0], matrix[1]);
-}
-
-static double
-get_matrix_vertical_component(double *matrix)
-{
- return hypot(matrix[2], matrix[3]);
-}
-
-
-static Bool
-ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to,
- double *dx, double *dy, double *sdx, double *sdy,
- double *rescale_x)
-{
- 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
- *sdx = *dx = 0;
-
- *rescale_x = 1.0;
-
- /* If client specified a width, it overrides setsize; in this
- context, we interpret width as applying to the font before any
- rotation, even though that's not what is ultimately returned in
- the width field. */
- if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS)
- {
- double rescale = (double)to->width / (double)from->width;
-
- /* If the client specified a transformation matrix, the rescaling
- for width does *not* override the setsize. Instead, just check
- for consistency between the setsize from the matrix and the
- setsize that would result from rescaling according to the width.
- This assumes (perhaps naively) that the width is correctly
- reported in the name. As an interesting side effect, this test
- may result in choosing a different source bitmap (one that
- scales consistently between the setsize *and* the width) than it
- would choose if a width were not specified. Sort of a hidden
- multiple-master functionality. */
- if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
- (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
- {
- /* Reject if resulting width difference is >= 1 pixel */
- if (fabs(rescale * from->width - *dx * from->width) >= 10)
- return FALSE;
- }
- else
- {
- *rescale_x = rescale/(*dx);
- *dx = rescale;
- }
- }
-
- if (srcpixel >= EPS)
- {
- *dy = destpixel / srcpixel;
- *sdy = 1000.0 / srcpixel;
- }
- else
- *sdy = *dy = 0;
-
- return TRUE;
-}
-
-/* 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 \
- score += (int)(((double)(3 * s)) / m); \
-} else { \
- score += (int)(((double)(2 * s)) * m); \
-}
-
-/* don't need to favor enlargement when looking for bitmap that can
- be used unscalable */
-#define SCORE2(m,s) \
-if (m >= 1.0) \
- score += (int)(((double)(8 * s)) / m); \
-else \
- score += (int)(((double)(8 * s)) * m);
-
-static FontEntryPtr
-FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry,
- FontScalablePtr vals, FontScalablePtr best,
- double *dxp, double *dyp,
- double *sdxp, double *sdyp,
- FontPathElementPtr *fpep)
-{
- FontScalableRec temp;
- int source, i;
- int best_score, best_unscaled_score,
- score;
- double dx = 0.0, sdx = 0.0, dx_amount = 0.0,
- dy = 0.0, sdy = 0.0, dy_amount = 0.0,
- best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0,
- best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0,
- best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0,
- rescale_x = 0.0, best_rescale_x = 0.0,
- best_unscaled_rescale_x = 0.0;
- FontEntryPtr zero;
- FontNameRec zeroName;
- char zeroChars[MAXFONTNAMELEN];
- FontDirectoryPtr dir;
- FontScaledPtr scaled;
- FontScalableExtraPtr extra;
- FontScaledPtr best_scaled, best_unscaled;
- FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL;
- FontEntryPtr bitmap = NULL;
- FontEntryPtr result;
- int aliascount = 20;
- FontPathElementPtr bitmap_fpe = NULL;
- FontNameRec xlfdName;
-
- /* find the best match */
- rescale_x = 1.0;
- best_scaled = 0;
- best_score = 0;
- best_unscaled = 0;
- best_unscaled_score = -1;
- best_dx_amount = best_dy_amount = HUGE_VAL;
- memcpy (zeroChars, entry->name.name, entry->name.length);
- zeroChars[entry->name.length] = '\0';
- zeroName.name = zeroChars;
- 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
- * can be scaled as desired.
- */
- 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
- {
- dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
- zero = FontFileFindNameInDir (&dir->scalable, &zeroName);
- if (!zero)
- continue;
- }
- extra = zero->u.scalable.extra;
- for (i = 0; i < extra->numScaled; i++)
- {
- scaled = &extra->scaled[i];
- if (!scaled->bitmap)
- continue;
- if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy,
- &rescale_x))
- continue;
- score = 0;
- dx_amount = dx;
- dy_amount = dy;
- SCORE(dy_amount, 10);
- SCORE(dx_amount, 1);
- if ((score > best_score) ||
- ((score == best_score) &&
- ((dy_amount < best_dy_amount) ||
- ((dy_amount == best_dy_amount) &&
- (dx_amount < best_dx_amount)))))
- {
- best_fpe = FontFileBitmapSources.fpe[source];
- best_scaled = scaled;
- 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;
- best_rescale_x = rescale_x;
- }
- /* Is this font a candidate for use without ugly rescaling? */
- if (fabs(dx) > EPS && fabs(dy) > EPS &&
- fabs(vals->pixel_matrix[0] * rescale_x -
- scaled->vals.pixel_matrix[0]) < 1 &&
- fabs(vals->pixel_matrix[1] * rescale_x -
- scaled->vals.pixel_matrix[1]) < EPS &&
- fabs(vals->pixel_matrix[2] -
- scaled->vals.pixel_matrix[2]) < EPS &&
- fabs(vals->pixel_matrix[3] -
- scaled->vals.pixel_matrix[3]) < 1)
- {
- /* Yes. The pixel sizes are close on the diagonal and
- extremely close off the diagonal. */
- score = 0;
- SCORE2(vals->pixel_matrix[3] /
- scaled->vals.pixel_matrix[3], 10);
- SCORE2(vals->pixel_matrix[0] * rescale_x /
- scaled->vals.pixel_matrix[0], 1);
- if (score > best_unscaled_score)
- {
- best_unscaled_fpe = FontFileBitmapSources.fpe[source];
- best_unscaled = scaled;
- best_unscaled_sdx = sdx / dx;
- best_unscaled_sdy = sdy / dy;
- best_unscaled_score = score;
- best_unscaled_rescale_x = rescale_x;
- }
- }
- }
- }
- if (best_unscaled)
- {
- *best = best_unscaled->vals;
- *fpep = best_unscaled_fpe;
- *dxp = 1.0;
- *dyp = 1.0;
- *sdxp = best_unscaled_sdx;
- *sdyp = best_unscaled_sdy;
- rescale_x = best_unscaled_rescale_x;
- result = best_unscaled->bitmap;
- }
- else if (best_scaled)
- {
- *best = best_scaled->vals;
- *fpep = best_fpe;
- *dxp = best_dx;
- *dyp = best_dy;
- *sdxp = best_sdx;
- *sdyp = best_sdy;
- rescale_x = best_rescale_x;
- 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);
- if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x))
- result = bitmap;
- else
- result = NULL;
- }
-
- if (result && rescale_x != 1.0)
- {
- /* We have rescaled horizontally due to an XLFD width field. Change
- the matrix appropriately */
- vals->pixel_matrix[0] *= rescale_x;
- vals->pixel_matrix[1] *= rescale_x;
-#ifdef NOTDEF
- /* This would force the pointsize and pixelsize fields in the
- FONT property to display as matrices to more accurately
- report the font being supplied. It might also break existing
- applications that expect a single number in that field. */
- vals->values_supplied =
- vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) |
- PIXELSIZE_ARRAY;
-#else /* NOTDEF */
- vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK;
-#endif /* NOTDEF */
- /* Recompute and reround the FontScalablePtr values after
- rescaling for the new width. */
- FontFileCompleteXLFD(vals, vals);
- }
-
- return result;
-}
-
-static FontEntryPtr
-FindPmfToScale(FontPathElementPtr fpe, FontEntryPtr entry,
- FontScalablePtr vals, FontScalablePtr best,
- double *dxp, double *dyp,
- double *sdxp, double *sdyp,
- FontPathElementPtr *fpep)
-{
- FontEntryPtr result = NULL;
- FontScaledPtr scaled;
- FontScalableExtraPtr extra;
- int i;
-
- extra = entry->u.scalable.extra;
- for (i = 0; i < extra->numScaled; i++)
- {
- double rescale_x;
-
- scaled = &extra->scaled[i];
- if (!scaled->bitmap)
- continue;
- if (!ComputeScaleFactors(&scaled->vals, vals, dxp, dyp, sdxp, sdyp,
- &rescale_x))
- continue;
- *best = scaled->vals;
- *fpep = fpe;
- result = scaled->bitmap;
- if (rescale_x != 1.0)
- {
- /* We have rescaled horizontally due to an XLFD width field. Change
- the matrix appropriately */
- vals->pixel_matrix[0] *= rescale_x;
- vals->pixel_matrix[1] *= rescale_x;
-#ifdef NOTDEF
- /* This would force the pointsize and pixelsize fields in the
- FONT property to display as matrices to more accurately
- report the font being supplied. It might also break existing
- applications that expect a single number in that field. */
- vals->values_supplied =
- vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) |
- PIXELSIZE_ARRAY;
-#else /* NOTDEF */
- vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK;
-#endif /* NOTDEF */
- /* Recompute and reround the FontScalablePtr values after
- rescaling for the new width. */
- FontFileCompleteXLFD(vals, vals);
- }
- break;
- }
- return result;
-}
-
-static long
-doround(double x)
-{
- return (x >= 0) ? (long)(x + .5) : (long)(x - .5);
-}
-
-static int
-computeProps(FontPropPtr pf, char *wasStringProp,
- FontPropPtr npf, char *isStringProp,
- unsigned int nprops, double xfactor, double yfactor,
- double sXfactor, double sYfactor)
-{
- int n;
- int count;
- fontProp *t;
- double rawfactor = 0.0;
-
- for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) {
- n = sizeof(fontPropTable) / sizeof(fontProp);
- for (t = fontPropTable; n && (t->atom != pf->name); n--, t++);
- if (!n)
- continue;
-
- switch (t->type) {
- case scaledX:
- npf->value = doround(xfactor * (double)pf->value);
- rawfactor = sXfactor;
- break;
- case scaledY:
- npf->value = doround(yfactor * (double)pf->value);
- rawfactor = sYfactor;
- break;
- case unscaled:
- npf->value = pf->value;
- npf->name = pf->name;
- npf++;
- count++;
- *isStringProp++ = *wasStringProp;
- break;
- default:
- break;
- }
- if (t->type != unscaled)
- {
- npf->name = pf->name;
- npf++;
- count++;
- npf->value = doround(rawfactor * (double)pf->value);
- npf->name = rawFontPropTable[t - fontPropTable].atom;
- npf++;
- count++;
- *isStringProp++ = *wasStringProp;
- *isStringProp++ = *wasStringProp;
- }
- }
- return count;
-}
-
-
-static int
-ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */
- char *name, /* name of resulting font */
- FontScalablePtr vals,
- double dx, double dy, /* scale factors in x and y */
- double sdx, double sdy, /* directions */
- long sWidth, /* 1000-pixel average width */
- FontPropPtr *pProps, /* returns properties;
- preallocated */
- char **pIsStringProp) /* return booleans;
- preallocated */
-{
- int n;
- char *ptr1 = NULL, *ptr2 = NULL;
- char *ptr3;
- FontPropPtr fp;
- fontProp *fpt;
- char *isStringProp;
- int nProps;
-
- if (bitscaleGeneration != serverGeneration) {
- initFontPropTable();
- bitscaleGeneration = serverGeneration;
- }
- nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) +
- sizeof(rawFontPropTable) / sizeof(fontProp);
- fp = (FontPropPtr) xalloc(sizeof(FontPropRec) * nProps);
- *pProps = fp;
- if (!fp) {
- fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n",
- (unsigned long)sizeof(FontPropRec), nProps);
- return 1;
- }
- isStringProp = (char *) xalloc (nProps);
- *pIsStringProp = isStringProp;
- if (!isStringProp)
- {
- fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps);
- xfree (fp);
- return 1;
- }
- ptr2 = name;
- for (fpt = fontNamePropTable, n = NPROPS;
- n;
- fp++, fpt++, n--, isStringProp++)
- {
-
- if (*ptr2)
- {
- ptr1 = ptr2 + 1;
- if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0');
- }
-
- *isStringProp = 0;
- switch (fpt->type) {
- case atom:
- fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE);
- *isStringProp = 1;
- break;
- case truncate_atom:
- for (ptr3 = ptr1; *ptr3; ptr3++)
- if (*ptr3 == '[')
- break;
- if (!*ptr3) ptr3 = ptr2;
- fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE);
- *isStringProp = 1;
- break;
- case pixel_size:
- fp->value = doround(vals->pixel_matrix[3]);
- break;
- case point_size:
- fp->value = doround(vals->point_matrix[3] * 10.0);
- break;
- case resolution_x:
- fp->value = vals->x;
- break;
- case resolution_y:
- fp->value = vals->y;
- break;
- 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;
- default:
- break;
- }
- fp->name = fpt->atom;
- }
- n = NPROPS;
- n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
- fp, isStringProp, sourceFontInfo->nprops, dx, dy,
- sdx, sdy);
- return n;
-}
-
-
-static int
-compute_xform_matrix(FontScalablePtr vals, double dx, double dy,
- double *xform, double *inv_xform,
- double *xmult, double *ymult)
-{
- double det;
- 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).
- */
-static FontPtr
-ScaleFont(FontPtr opf, /* originating font */
- double widthMult, /* glyphs width scale factor */
- double heightMult, /* glyphs height scale factor */
- 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,
- opfi;
- BitmapFontPtr bitmapFont,
- obitmapFont;
- CharInfoPtr pci,
- opci;
- int nchars = 0; /* how many characters in the font */
- int i;
- int firstCol, lastCol, firstRow, lastRow;
- double xform[4], inv_xform[4];
- double xmult, ymult;
- int totalwidth = 0, totalchars = 0;
-#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)
-
- *sWidth = 0;
-
- opfi = &opf->info;
- obitmapFont = (BitmapFontPtr) opf->fontPrivate;
-
- bitmapFont = 0;
- if (!(pf = CreateFontRec())) {
- fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n",
- (unsigned long)sizeof(FontRec));
- goto bail;
- }
- pf->refcnt = 0;
- pf->bit = opf->bit;
- pf->byte = opf->byte;
- pf->glyph = opf->glyph;
- pf->scan = opf->scan;
-
- 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) {
- fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n",
- (unsigned long)sizeof(BitmapFontRec));
- goto bail;
- }
- 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 = nchars;
- bitmapFont->num_tables = obitmapFont->num_tables;
- bitmapFont->metrics = 0;
- bitmapFont->ink_metrics = 0;
- bitmapFont->bitmaps = 0;
- bitmapFont->encoding = 0;
- bitmapFont->bitmapExtra = 0;
- bitmapFont->pDefault = 0;
- bitmapFont->metrics = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec));
- if (!bitmapFont->metrics) {
- fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n",
- nchars, (unsigned long)sizeof(CharInfoRec));
- goto bail;
- }
- bitmapFont->encoding =
- (CharInfoPtr **) xcalloc(NUM_SEGMENTS(nchars),
- sizeof(CharInfoPtr*));
- if (!bitmapFont->encoding) {
- fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n",
- nchars, (unsigned long)sizeof(CharInfoPtr));
- goto bail;
- }
-
-#undef MAXSHORT
-#define MAXSHORT 32767
-#undef MINSHORT
-#define MINSHORT -32768
-
- pfi->anamorphic = FALSE;
- if (heightMult != widthMult)
- pfi->anamorphic = TRUE;
- pfi->cachable = TRUE;
-
- 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. */
-
- pci = bitmapFont->metrics;
- for (i = 0; i < nchars; i++)
- {
- if ((opci = ACCESSENCODING(obitmapFont->encoding,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)
- {
- continue;
- }
- }
-
- if (opci->metrics.leftSideBearing == 0 &&
- opci->metrics.rightSideBearing == 0 &&
- opci->metrics.ascent == 0 &&
- opci->metrics.descent == 0 &&
- opci->metrics.characterWidth == 0)
- {
- continue;
- }
-
- if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
- bitmapFont->encoding[SEGMENT_MAJOR(i)]=
- (CharInfoPtr*)xcalloc(BITMAP_FONT_SEGMENT_SIZE,
- sizeof(CharInfoPtr));
- if(!bitmapFont->encoding[SEGMENT_MAJOR(i)])
- goto bail;
- }
- ACCESSENCODINGL(bitmapFont->encoding, i) = pci;
-
- /* 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);
- /* Accumulate total width of characters before transformation,
- to ascertain predominant direction of font. */
- totalwidth += opci->metrics.characterWidth;
- 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++;
- }
-
- pci++;
- }
- }
-
-
- /*
- * For each character, set the per-character metrics, scale the glyph, and
- * check per-font minbounds and maxbounds character information.
- */
-
- pci = bitmapFont->metrics;
- for (i = 0; i < nchars; i++)
- {
- if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) &&
- (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))))
- {
- totalchars++;
- *sWidth += abs((int)(INT16)pci->metrics.attributes);
-#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)
- {
- *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars;
- if (totalwidth < 0)
- {
- /* Dominant direction is R->L */
- *sWidth = -*sWidth;
- }
-
- if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth)
- vals->width = pfi->minbounds.characterWidth * 10;
- else
- vals->width = doround((double)*sWidth * vals->pixel_matrix[0] /
- 1000.0);
- }
- else
- {
- vals->width = 0;
- *sWidth = 0;
- }
- FontComputeInfoAccelerators (pfi);
-
- if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) {
- unsigned int r,
- c,
- cols;
-
- r = pfi->defaultCh >> 8;
- c = pfi->defaultCh & 0xFF;
- if (pfi->firstRow <= r && r <= pfi->lastRow &&
- pfi->firstCol <= c && c <= pfi->lastCol) {
- cols = pfi->lastCol - pfi->firstCol + 1;
- r = r - pfi->firstRow;
- c = c - pfi->firstCol;
- bitmapFont->pDefault =
- ACCESSENCODING(bitmapFont->encoding, r * cols + c);
- }
- }
-
- *newWidthMult = xmult;
- *newHeightMult = ymult;
- return pf;
-bail:
- if (pf)
- xfree(pf);
- if (bitmapFont) {
- xfree(bitmapFont->metrics);
- xfree(bitmapFont->ink_metrics);
- xfree(bitmapFont->bitmaps);
- if(bitmapFont->encoding)
- for(i=0; i<NUM_SEGMENTS(nchars); i++)
- xfree(bitmapFont->encoding[i]);
- xfree(bitmapFont->encoding);
- }
- return NULL;
-}
-
-static void
-ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci,
- double *inv_xform, double widthMult, double heightMult)
-{
- register char *bitmap, /* The bits */
- *newBitmap;
- register int bpr, /* Padding information */
- newBpr;
- int width, /* Extents information */
- height,
- newWidth,
- newHeight;
- register 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 = NULL, *thisrow = NULL,
- *nextrow = NULL, pixmult = 0;
- int box_x = 0, box_y = 0;
-
- 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;
- width = GLYPHWIDTHPIXELS(opci);
- height = GLYPHHEIGHTPIXELS(opci);
- newWidth = GLYPHWIDTHPIXELS(pci);
- newHeight = GLYPHHEIGHTPIXELS(pci);
- if (!newWidth || !newHeight || !width || !height)
- return;
-
- 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 = ceil(1.0 / widthMult);
- heightMult = ceil(1.0 / heightMult);
- box_x = width / 2;
- box_y = height / 2;
- if (widthMult < (double)box_x) box_x = (int)widthMult;
- if (heightMult < (double)box_y) box_y = (int)heightMult;
- /* The pixmult value (below) is used to darken the image before
- we perform error diffusion: a necessary concession to the
- fact that it's very difficult to generate readable halftoned
- glyphs. The degree of darkening is proportional to the size
- of the blurring filter, hence inversely proportional to the
- darkness of the lightest gray that results from antialiasing.
- The result is that characters that exercise this logic (those
- generated by reducing from a larger source font) tend to err
- on the side of being too bold instead of being too light to
- be readable. */
- pixmult = box_x * box_y * 192;
-
- 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)
- {
- fprintf(stderr, "Warning: Couldn't allocate diffusion"
- " workspace (%ld)\n",
- (newWidth + 2) * 2 * (unsigned long)sizeof(int));
- 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;
- } else {
- fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 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]. */
- register 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++;
- }
-
- /* 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++;
- }
-
- /* Done with the row... copy dest back over source */
- memmove(char_grayscale + (width + 1) * row,
- char_grayscale + (width + 1) * height,
- width);
- }
- }
- 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;
- }
-
- /* 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;
- }
- }
- }
-
- /* Increase the grayvalue to increase ink a bit */
- srcptr = char_grayscale;
- for (row = 0; row < height; row++)
- {
- for (col = 0; col < width; col++)
- {
- register int pixvalue = (int)*srcptr * pixmult / 256;
- if (pixvalue > 255) pixvalue = 255;
- *srcptr = pixvalue;
- srcptr++;
- }
- srcptr++;
- }
- }
-
- /* 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;
- 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;
- }
-
- /* 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++)
- {
- 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;
- }
- }
- }
-
-
- if (char_grayscale)
- {
- xfree(char_grayscale);
- xfree(diffusion_workspace);
- }
-}
-
-static FontPtr
-BitmapScaleBitmaps(FontPtr pf, /* scaled font */
- FontPtr opf, /* originating font */
- double widthMult, /* glyphs width scale factor */
- double heightMult, /* glyphs height scale factor */
- FontScalablePtr vals)
-{
- register int i;
- int nchars = 0;
- char *glyphBytes;
- BitmapFontPtr bitmapFont,
- obitmapFont;
- CharInfoPtr pci,
- opci;
- FontInfoPtr pfi;
- int glyph;
- unsigned bytestoalloc = 0;
- int firstCol, lastCol, firstRow, lastRow;
-
- double xform[4], inv_xform[4];
- double xmult, ymult;
-
- bitmapFont = (BitmapFontPtr) pf->fontPrivate;
- obitmapFont = (BitmapFontPtr) opf->fontPrivate;
-
- if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
- inv_xform, &xmult, &ymult))
- goto bail;
-
- pfi = &pf->info;
- firstCol = pfi->firstCol;
- lastCol = pfi->lastCol;
- firstRow = pfi->firstRow;
- lastRow = pfi->lastRow;
-
- nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
- glyph = pf->glyph;
- for (i = 0; i < nchars; i++)
- {
- if ((pci = ACCESSENCODING(bitmapFont->encoding, i)))
- bytestoalloc += BYTES_FOR_GLYPH(pci, glyph);
- }
-
- /* Do we add the font malloc stuff for VALUE ADDED ? */
- /* Will need to remember to free in the Unload routine */
-
-
- bitmapFont->bitmaps = (char *) xalloc(bytestoalloc);
- if (!bitmapFont->bitmaps) {
- fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc);
- goto bail;
- }
- bzero(bitmapFont->bitmaps, bytestoalloc);
-
- glyphBytes = bitmapFont->bitmaps;
- for (i = 0; i < nchars; i++)
- {
- if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) &&
- (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i))))
- {
- pci->bits = glyphBytes;
- ScaleBitmap (pf, opci, pci, inv_xform,
- widthMult, heightMult);
- glyphBytes += BYTES_FOR_GLYPH(pci, glyph);
- }
- }
- return pf;
-
-bail:
- if (pf)
- xfree(pf);
- if (bitmapFont) {
- xfree(bitmapFont->metrics);
- xfree(bitmapFont->ink_metrics);
- xfree(bitmapFont->bitmaps);
- if(bitmapFont->encoding)
- for(i=0; i<NUM_SEGMENTS(nchars); i++)
- xfree(bitmapFont->encoding[i]);
- xfree(bitmapFont->encoding);
- }
- return NULL;
-}
-
-static FontPtr
-PrinterScaleBitmaps(FontPtr pf, /* scaled font */
- FontPtr opf, /* originating font */
- double widthMult, /* glyphs width scale factor */
- double heightMult, /* glyphs height scale factor */
- FontScalablePtr vals)
-{
- register int i;
- int nchars = 0;
- char *glyphBytes;
- BitmapFontPtr bitmapFont,
- obitmapFont;
- CharInfoPtr pci;
- FontInfoPtr pfi;
- int glyph;
- unsigned bytestoalloc = 0;
- int firstCol, lastCol, firstRow, lastRow;
-
- double xform[4], inv_xform[4];
- double xmult, ymult;
-
- bitmapFont = (BitmapFontPtr) pf->fontPrivate;
- obitmapFont = (BitmapFontPtr) opf->fontPrivate;
-
- if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
- inv_xform, &xmult, &ymult))
- goto bail;
-
- pfi = &pf->info;
- firstCol = pfi->firstCol;
- lastCol = pfi->lastCol;
- firstRow = pfi->firstRow;
- lastRow = pfi->lastRow;
-
- nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
- glyph = pf->glyph;
- for (i = 0; i < nchars; i++)
- {
- if ((pci = ACCESSENCODING(bitmapFont->encoding, i)))
- bytestoalloc = MAX(bytestoalloc,BYTES_FOR_GLYPH(pci, glyph));
- }
-
- /* Do we add the font malloc stuff for VALUE ADDED ? */
- /* Will need to remember to free in the Unload routine */
-
-
- bitmapFont->bitmaps = (char *) xalloc(bytestoalloc);
- if (!bitmapFont->bitmaps) {
- fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc);
- goto bail;
- }
- bzero(bitmapFont->bitmaps, bytestoalloc);
-
- glyphBytes = bitmapFont->bitmaps;
- for (i = 0; i < nchars; i++)
- {
- if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) &&
- (ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i))))
- {
- pci->bits = glyphBytes;
- }
- }
- return pf;
-
-bail:
- if (pf)
- xfree(pf);
- if (bitmapFont) {
- xfree(bitmapFont->metrics);
- xfree(bitmapFont->ink_metrics);
- xfree(bitmapFont->bitmaps);
- if(bitmapFont->encoding)
- for(i=0; i<NUM_SEGMENTS(nchars); i++)
- xfree(bitmapFont->encoding[i]);
- xfree(bitmapFont->encoding);
- }
- return NULL;
-}
-
-#ifdef NOTDEF
-/*
- * exported interfaces
- */
-
-FontFileLoadName(FontFileDirPtr *dirs, int ndirs, char *name, FontPtr *pfont,
- fsBitmapFormat format, fsBitmapFormatMask fmask)
-{
- FontFileNamePtr fname;
- char full_name[1024];
- int ret = BadFontName;
- int i;
-
- i = 0;
- while (i < ndirs) {
- if (fname = FontFileFindNameInDir(dirs[i], name)) {
- if (!fname->alias) {
- if (!fname->font) {
- strcpy(full_name, dirs[i]->dir);
- strcat(full_name, fname->file);
- ret = FontFileLoad(pfont, full_name, format, fmask);
- if (ret == Successful) {
- fname->font = *pfont;
- (*pfont)->fpePrivate = (pointer) fname;
- }
- return ret;
- }
- *pfont = fname->font;
- return Successful;
- }
- name = fname->file;
- i = 0;
- } else
- i++;
- }
- return BadFontName;
-}
-#endif
-
-/* ARGSUSED */
-int
-BitmapOpenScalable (FontPathElementPtr fpe,
- FontPtr *pFont,
- int flags,
- FontEntryPtr entry,
- char *fileName, /* unused */
- FontScalablePtr vals,
- fsBitmapFormat format,
- fsBitmapFormatMask fmask,
- FontPtr non_cachable_font) /* We don't do licensing */
-{
- FontScalableRec best;
- FontPtr font = NullFont;
- double dx, sdx,
- dy, sdy,
- savedX, savedY;
- FontPropPtr props;
- char *isStringProp;
- int propCount;
- int status;
- long sWidth;
-
- FontEntryPtr scaleFrom;
- FontPathElementPtr scaleFPE;
- FontPtr sourceFont;
- char fontName[MAXFONTNAMELEN];
-
- /* Can't deal with mix-endian fonts yet */
-
-#ifdef NOTDEF /* XXX need better test */
- if ((format & BitmapFormatByteOrderMask) !=
- (format & BitmapFormatBitOrderMask))
- return NullFontFileName;
-#endif
-
- /* Reject outrageously small font sizes to keep the math from
- blowing up. */
- if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 ||
- get_matrix_horizontal_component(vals->pixel_matrix) < 1.0)
- return BadFontName;
-
- scaleFrom = (*find_scale[BitmapGetRenderIndex(entry->u.bitmap.renderer)])
- (fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy, &scaleFPE);
-
- if (!scaleFrom)
- return BadFontName;
-
- status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom,
- format, fmask);
-
- if (status != Successful)
- return BadFontName;
-
- if (!vals->width)
- vals->width = best.width * dx;
-
- /* Compute the scaled font */
-
- savedX = dx;
- savedY = dy;
- font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth);
- if (font)
- font = (*scale[ BitmapGetRenderIndex(entry->u.bitmap.renderer) ])
- (font, sourceFont, savedX, savedY, vals);
-
- if (!font)
- {
- if (!sourceFont->refcnt)
- FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
- return AllocError;
- }
-
- /* Prepare font properties for the new font */
-
- strcpy (fontName, scaleFrom->name.name);
- FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE);
-
- propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals,
- dx, dy, sdx, sdy, sWidth, &props,
- &isStringProp);
-
- if (!sourceFont->refcnt)
- FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
-
- if (propCount && (!props || !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;
-}
-
-int
-BitmapGetInfoScalable (FontPathElementPtr fpe,
- FontInfoPtr pFontInfo,
- FontEntryPtr entry,
- FontNamePtr fontName,
- char *fileName,
- FontScalablePtr vals)
-{
- 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, NULL);
- if (ret != Successful)
- return ret;
- *pFontInfo = pfont->info;
-
- pfont->info.nprops = 0;
- pfont->info.props = NULL;
- pfont->info.isStringProp = NULL;
-
- (*pfont->unload_font)(pfont);
- return Successful;
-}
-
-static void
-bitmapUnloadScalable (FontPtr pFont)
-{
- BitmapFontPtr bitmapFont;
- FontInfoPtr pfi;
- int i, nencoding;
-
- bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
- pfi = &pFont->info;
- xfree (pfi->props);
- xfree (pfi->isStringProp);
- if(bitmapFont->encoding) {
- nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
- (pFont->info.lastRow - pFont->info.firstRow + 1);
- for(i=0; i<NUM_SEGMENTS(nencoding); i++)
- xfree(bitmapFont->encoding[i]);
- }
- xfree (bitmapFont->encoding);
- xfree (bitmapFont->bitmaps);
- xfree (bitmapFont->ink_metrics);
- xfree (bitmapFont->metrics);
- xfree (pFont->fontPrivate);
- DestroyFontRec (pFont);
-}