#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/fonts/fntfilst.h>
#include <math.h>
Bool
FontFileAddScaledInstance (FontEntryPtr entry, FontScalablePtr vals,
FontPtr pFont, char *bitmapName)
{
FontScalableEntryPtr scalable;
FontScalableExtraPtr extra;
FontScaledPtr new;
int newsize;
scalable = &entry->u.scalable;
extra = scalable->extra;
if (extra->numScaled == extra->sizeScaled)
{
newsize = extra->sizeScaled + 4;
new = realloc (extra->scaled, newsize * sizeof (FontScaledRec));
if (!new)
return FALSE;
extra->sizeScaled = newsize;
extra->scaled = new;
}
new = &extra->scaled[extra->numScaled++];
new->vals = *vals;
new->pFont = pFont;
new->bitmap = (FontEntryPtr) bitmapName;
if (pFont)
pFont->fpePrivate = (pointer) entry;
return TRUE;
}
void
FontFileSwitchStringsToBitmapPointers (FontDirectoryPtr dir)
{
int s;
int b;
int i;
FontEntryPtr scalable;
FontEntryPtr nonScalable;
FontScaledPtr scaled;
FontScalableExtraPtr extra;
scalable = dir->scalable.entries;
nonScalable = dir->nonScalable.entries;
for (s = 0; s < dir->scalable.used; s++)
{
extra = scalable[s].u.scalable.extra;
scaled = extra->scaled;
for (i = 0; i < extra->numScaled; i++)
for (b = 0; b < dir->nonScalable.used; b++)
if (nonScalable[b].name.name == (char *) scaled[i].bitmap)
scaled[i].bitmap = &nonScalable[b];
}
}
void
FontFileRemoveScaledInstance (FontEntryPtr entry, FontPtr pFont)
{
FontScalableEntryPtr scalable;
FontScalableExtraPtr extra;
int i;
scalable = &entry->u.scalable;
extra = scalable->extra;
for (i = 0; i < extra->numScaled; i++)
{
if (extra->scaled[i].pFont == pFont)
{
if (extra->scaled[i].vals.ranges)
free (extra->scaled[i].vals.ranges);
extra->numScaled--;
for (; i < extra->numScaled; i++)
extra->scaled[i] = extra->scaled[i+1];
}
}
}
Bool
FontFileCompleteXLFD (FontScalablePtr vals, FontScalablePtr def)
{
FontResolutionPtr res;
int num_res;
double sx, sy, temp_matrix[4];
double pixel_setsize_adjustment = 1.0;
res = GetClientResolutions(&num_res);
if (!(vals->values_supplied & PIXELSIZE_MASK) ||
!(vals->values_supplied & POINTSIZE_MASK))
{
if (num_res)
{
if (vals->x <= 0)
vals->x = res->x_resolution;
if (vals->y <= 0)
vals->y = res->y_resolution;
}
if (vals->x <= 0)
vals->x = def->x;
if (vals->y <= 0)
vals->y = def->y;
}
else
{
if (vals->y <= 0)
{
double x = hypot(vals->pixel_matrix[1], vals->pixel_matrix[3]);
double y = hypot(vals->point_matrix[1], vals->point_matrix[3]);
if (y < EPS) return FALSE;
vals->y = (int)(x * 72.27 / y + .5);
}
if (vals->x <= 0)
{
if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
(vals->values_supplied & PIXELSIZE_MASK) ==
PIXELSIZE_SCALAR_NORMALIZED)
{
double x = hypot(vals->pixel_matrix[0], vals->pixel_matrix[2]);
double y = hypot(vals->point_matrix[0], vals->point_matrix[2]);
if (y < EPS) return FALSE;
vals->x = (int)(x * 72.27 / y + .5);
}
else
{
vals->x = vals->y;
}
}
}
if (vals->x <= 0 || vals->y <= 0) return FALSE;
if (!(vals->values_supplied & PIXELSIZE_MASK) &&
!(vals->values_supplied & POINTSIZE_MASK))
{
if (num_res)
{
vals->point_matrix[0] =
vals->point_matrix[3] = (double)res->point_size / 10.0;
vals->point_matrix[1] =
vals->point_matrix[2] = 0;
vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) |
POINTSIZE_SCALAR;
}
else if (def->values_supplied & POINTSIZE_MASK)
{
vals->point_matrix[0] = def->point_matrix[0];
vals->point_matrix[1] = def->point_matrix[1];
vals->point_matrix[2] = def->point_matrix[2];
vals->point_matrix[3] = def->point_matrix[3];
vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) |
(def->values_supplied & POINTSIZE_MASK);
}
else return FALSE;
}
if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_SCALAR)
{
pixel_setsize_adjustment = (double)vals->x / (double)vals->y;
vals->pixel_matrix[0] *= pixel_setsize_adjustment;
vals->values_supplied = (vals->values_supplied & ~PIXELSIZE_MASK) |
PIXELSIZE_SCALAR_NORMALIZED;
}
sx = (double)vals->x / 72.27;
sy = (double)vals->y / 72.27;
if (vals->values_supplied & POINTSIZE_MASK)
{
recompute_pixelsize: ;
temp_matrix[0] = vals->point_matrix[0] * sx;
temp_matrix[1] = vals->point_matrix[1] * sy;
temp_matrix[2] = vals->point_matrix[2] * sx;
temp_matrix[3] = vals->point_matrix[3] * sy;
if (vals->values_supplied & PIXELSIZE_MASK)
{
if (fabs(vals->pixel_matrix[0] - temp_matrix[0]) >
pixel_setsize_adjustment ||
fabs(vals->pixel_matrix[1] - temp_matrix[1]) > 1 ||
fabs(vals->pixel_matrix[2] - temp_matrix[2]) > 1 ||
fabs(vals->pixel_matrix[3] - temp_matrix[3]) > 1)
return FALSE;
}
if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY &&
(vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR)
{
goto recompute_pointsize;
}
vals->pixel_matrix[0] = temp_matrix[0];
vals->pixel_matrix[1] = temp_matrix[1];
vals->pixel_matrix[2] = temp_matrix[2];
vals->pixel_matrix[3] = temp_matrix[3];
vals->values_supplied =
(vals->values_supplied & ~PIXELSIZE_MASK) |
(((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) ?
PIXELSIZE_ARRAY : PIXELSIZE_SCALAR_NORMALIZED);
}
else
{
recompute_pointsize: ;
if (fabs(sx) < EPS || fabs(sy) < EPS) return FALSE;
vals->point_matrix[0] = vals->pixel_matrix[0] / sx;
vals->point_matrix[1] = vals->pixel_matrix[1] / sy;
vals->point_matrix[2] = vals->pixel_matrix[2] / sx;
vals->point_matrix[3] = vals->pixel_matrix[3] / sy;
vals->values_supplied =
(vals->values_supplied & ~POINTSIZE_MASK) |
(((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY) ?
POINTSIZE_ARRAY : POINTSIZE_SCALAR);
if ((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR)
{
vals->point_matrix[0] =
(double)(int)(vals->point_matrix[0] * 10.0 + .5) / 10.0;
vals->point_matrix[3] =
(double)(int)(vals->point_matrix[3] * 10.0 + .5) / 10.0;
goto recompute_pixelsize;
}
}
vals->pixel_matrix[0] = xlfd_round_double(vals->pixel_matrix[0]);
vals->pixel_matrix[1] = xlfd_round_double(vals->pixel_matrix[1]);
vals->pixel_matrix[2] = xlfd_round_double(vals->pixel_matrix[2]);
vals->pixel_matrix[3] = xlfd_round_double(vals->pixel_matrix[3]);
vals->point_matrix[0] = xlfd_round_double(vals->point_matrix[0]);
vals->point_matrix[1] = xlfd_round_double(vals->point_matrix[1]);
vals->point_matrix[2] = xlfd_round_double(vals->point_matrix[2]);
vals->point_matrix[3] = xlfd_round_double(vals->point_matrix[3]);
vals->point = vals->point_matrix[3] * 10;
vals->pixel = vals->pixel_matrix[3];
return TRUE;
}
static Bool
MatchScalable (FontScalablePtr a, FontScalablePtr b)
{
int i;
#define EQUAL(a,b) ((a)[0] == (b)[0] && \
(a)[1] == (b)[1] && \
(a)[2] == (b)[2] && \
(a)[3] == (b)[3])
if (!(a->x == b->x &&
a->y == b->y &&
(a->width == b->width || a->width == 0 || b->width == 0 || b->width == -1) &&
(!(b->values_supplied & PIXELSIZE_MASK) ||
((a->values_supplied & PIXELSIZE_MASK) ==
(b->values_supplied & PIXELSIZE_MASK) &&
EQUAL(a->pixel_matrix, b->pixel_matrix))) &&
(!(b->values_supplied & POINTSIZE_MASK) ||
((a->values_supplied & POINTSIZE_MASK) ==
(b->values_supplied & POINTSIZE_MASK) &&
EQUAL(a->point_matrix, b->point_matrix))) &&
(a->nranges == 0 || a->nranges == b->nranges)))
return FALSE;
for (i = 0; i < a->nranges; i++)
if (a->ranges[i].min_char_low != b->ranges[i].min_char_low ||
a->ranges[i].min_char_high != b->ranges[i].min_char_high ||
a->ranges[i].max_char_low != b->ranges[i].max_char_low ||
a->ranges[i].max_char_high != b->ranges[i].max_char_high)
return FALSE;
return TRUE;
}
FontScaledPtr
FontFileFindScaledInstance (FontEntryPtr entry, FontScalablePtr vals,
int noSpecificSize)
{
FontScalableEntryPtr scalable;
FontScalableExtraPtr extra;
FontScalablePtr mvals;
int dist, i;
int mini;
double mindist;
register double temp, sum=0.0;
#define NORMDIFF(a, b) ( \
temp = (a)[0] - (b)[0], \
sum = temp * temp, \
temp = (a)[1] - (b)[1], \
sum += temp * temp, \
temp = (a)[2] - (b)[2], \
sum += temp * temp, \
temp = (a)[3] - (b)[3], \
sum + temp * temp )
scalable = &entry->u.scalable;
extra = scalable->extra;
if (noSpecificSize && extra->numScaled)
{
mini = 0;
mindist = NORMDIFF(extra->scaled[0].vals.point_matrix,
vals->point_matrix);
for (i = 1; i < extra->numScaled; i++)
{
if (extra->scaled[i].pFont &&
!extra->scaled[i].pFont->info.cachable) continue;
mvals = &extra->scaled[i].vals;
dist = NORMDIFF(mvals->point_matrix, vals->point_matrix);
if (dist < mindist)
{
mindist = dist;
mini = i;
}
}
if (extra->scaled[mini].pFont &&
!extra->scaled[mini].pFont->info.cachable) return 0;
return &extra->scaled[mini];
}
else
{
for (i = 0; i < extra->numScaled; i++)
{
if (extra->scaled[i].pFont &&
!extra->scaled[i].pFont->info.cachable) continue;
if (MatchScalable (&extra->scaled[i].vals, vals))
return &extra->scaled[i];
}
}
return 0;
}