summaryrefslogtreecommitdiff
path: root/xc/lib/font/bitmap
diff options
context:
space:
mode:
authorgildea <empty>1993-08-24 18:48:45 +0000
committergildea <empty>1993-08-24 18:48:45 +0000
commit9048cf6bfb9b5f3e02648efb14bd2aac9423d641 (patch)
treead165900172f0288545ef56f22263a0c35825422 /xc/lib/font/bitmap
parent8214a8d0315029e24214b802065067054822101a (diff)
Nathan Meyers: XLFD matrix, glyph caching, font auth
Diffstat (limited to 'xc/lib/font/bitmap')
-rw-r--r--xc/lib/font/bitmap/bdfread.c4
-rw-r--r--xc/lib/font/bitmap/bitmapfunc.c11
-rw-r--r--xc/lib/font/bitmap/bitscale.c1319
-rw-r--r--xc/lib/font/bitmap/pcfread.c4
-rw-r--r--xc/lib/font/bitmap/snfread.c5
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;