Blame src/xftfreetype.c

Packit Service 1b8107
/*
Packit Service 1b8107
 * Copyright © 2000 Keith Packard
Packit Service 1b8107
 *
Packit Service 1b8107
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit Service 1b8107
 * documentation for any purpose is hereby granted without fee, provided that
Packit Service 1b8107
 * the above copyright notice appear in all copies and that both that
Packit Service 1b8107
 * copyright notice and this permission notice appear in supporting
Packit Service 1b8107
 * documentation, and that the name of Keith Packard not be used in
Packit Service 1b8107
 * advertising or publicity pertaining to distribution of the software without
Packit Service 1b8107
 * specific, written prior permission.  Keith Packard makes no
Packit Service 1b8107
 * representations about the suitability of this software for any purpose.  It
Packit Service 1b8107
 * is provided "as is" without express or implied warranty.
Packit Service 1b8107
 *
Packit Service 1b8107
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit Service 1b8107
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit Service 1b8107
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit Service 1b8107
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit Service 1b8107
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit Service 1b8107
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit Service 1b8107
 * PERFORMANCE OF THIS SOFTWARE.
Packit Service 1b8107
 */
Packit Service 1b8107
Packit Service 1b8107
#include "xftint.h"
Packit Service 1b8107
Packit Service 1b8107
_X_HIDDEN FT_Library  _XftFTlibrary;
Packit Service 1b8107
Packit Service 1b8107
#define FT_Matrix_Equal(a,b)	((a)->xx == (b)->xx && \
Packit Service 1b8107
				 (a)->yy == (b)->yy && \
Packit Service 1b8107
				 (a)->xy == (b)->xy && \
Packit Service 1b8107
				 (a)->yx == (b)->yx)
Packit Service 1b8107
/*
Packit Service 1b8107
 * List of all open files (each face in a file is managed separately)
Packit Service 1b8107
 */
Packit Service 1b8107
Packit Service 1b8107
static XftFtFile *_XftFtFiles;
Packit Service 1b8107
static int XftMaxFreeTypeFiles = 5;
Packit Service 1b8107
Packit Service 1b8107
static XftFtFile *
Packit Service 1b8107
_XftGetFile (const FcChar8 *file, int id)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFtFile	*f;
Packit Service 1b8107
Packit Service 1b8107
    if (!XftInitFtLibrary ())
Packit Service 1b8107
	return NULL;
Packit Service 1b8107
Packit Service 1b8107
    for (f = _XftFtFiles; f; f = f->next)
Packit Service 1b8107
    {
Packit Service 1b8107
	if (!strcmp (f->file, (char *) file) && f->id == id)
Packit Service 1b8107
	{
Packit Service 1b8107
	    ++f->ref;
Packit Service 1b8107
	    if (XftDebug () & XFT_DBG_REF)
Packit Service 1b8107
		printf ("FontFile %s/%d matches existing (%d)\n",
Packit Service 1b8107
			file, id, f->ref);
Packit Service 1b8107
	    return f;
Packit Service 1b8107
	}
Packit Service 1b8107
    }
Packit Service 1b8107
    f = malloc (sizeof (XftFtFile) + strlen ((char *) file) + 1);
Packit Service 1b8107
    if (!f)
Packit Service 1b8107
	return NULL;
Packit Service 1b8107
Packit Service 1b8107
    XftMemAlloc (XFT_MEM_FILE, sizeof (XftFtFile) + strlen ((char *) file) + 1);
Packit Service 1b8107
    if (XftDebug () & XFT_DBG_REF)
Packit Service 1b8107
    	printf ("FontFile %s/%d matches new\n",
Packit Service 1b8107
		file, id);
Packit Service 1b8107
    f->next = _XftFtFiles;
Packit Service 1b8107
    _XftFtFiles = f;
Packit Service 1b8107
Packit Service 1b8107
    f->ref = 1;
Packit Service 1b8107
Packit Service 1b8107
    f->file = (char *) (f+1);
Packit Service 1b8107
    strcpy (f->file, (char *) file);
Packit Service 1b8107
    f->id = id;
Packit Service 1b8107
Packit Service 1b8107
    f->lock = 0;
Packit Service 1b8107
    f->face = NULL;
Packit Service 1b8107
    f->xsize = 0;
Packit Service 1b8107
    f->ysize = 0;
Packit Service 1b8107
    f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0;
Packit Service 1b8107
    return f;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static XftFtFile *
Packit Service 1b8107
_XftGetFaceFile (FT_Face face)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFtFile	*f;
Packit Service 1b8107
Packit Service 1b8107
    f = malloc (sizeof (XftFtFile));
Packit Service 1b8107
    if (!f)
Packit Service 1b8107
	return NULL;
Packit Service 1b8107
    XftMemAlloc (XFT_MEM_FILE, sizeof(XftFtFile));
Packit Service 1b8107
    f->next = NULL;
Packit Service 1b8107
Packit Service 1b8107
    f->ref = 1;
Packit Service 1b8107
Packit Service 1b8107
    f->file = NULL;
Packit Service 1b8107
    f->id = 0;
Packit Service 1b8107
    f->lock = 0;
Packit Service 1b8107
    f->face = face;
Packit Service 1b8107
    f->xsize = 0;
Packit Service 1b8107
    f->ysize = 0;
Packit Service 1b8107
    f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0;
Packit Service 1b8107
    return f;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static int
Packit Service 1b8107
_XftNumFiles (void)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFtFile	*f;
Packit Service 1b8107
    int		count = 0;
Packit Service 1b8107
    for (f = _XftFtFiles; f; f = f->next)
Packit Service 1b8107
	if (f->face && !f->lock)
Packit Service 1b8107
	    ++count;
Packit Service 1b8107
    return count;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static XftFtFile *
Packit Service 1b8107
_XftNthFile (int n)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFtFile	*f;
Packit Service 1b8107
    int		count = 0;
Packit Service 1b8107
    for (f = _XftFtFiles; f; f = f->next)
Packit Service 1b8107
	if (f->face && !f->lock)
Packit Service 1b8107
	    if (count++ == n)
Packit Service 1b8107
		break;
Packit Service 1b8107
    return f;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static void
Packit Service 1b8107
_XftUncacheFiles (void)
Packit Service 1b8107
{
Packit Service 1b8107
    int		n;
Packit Service 1b8107
    XftFtFile	*f;
Packit Service 1b8107
    while ((n = _XftNumFiles ()) > XftMaxFreeTypeFiles)
Packit Service 1b8107
    {
Packit Service 1b8107
	f = _XftNthFile (rand () % n);
Packit Service 1b8107
	if (f)
Packit Service 1b8107
	{
Packit Service 1b8107
	    if (XftDebug() & XFT_DBG_REF)
Packit Service 1b8107
		printf ("Discard file %s/%d from cache\n",
Packit Service 1b8107
			f->file, f->id);
Packit Service 1b8107
	    FT_Done_Face (f->face);
Packit Service 1b8107
	    f->face = NULL;
Packit Service 1b8107
	}
Packit Service 1b8107
    }
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static FT_Face
Packit Service 1b8107
_XftLockFile (XftFtFile *f)
Packit Service 1b8107
{
Packit Service 1b8107
    ++f->lock;
Packit Service 1b8107
    if (!f->face)
Packit Service 1b8107
    {
Packit Service 1b8107
	if (XftDebug() & XFT_DBG_REF)
Packit Service 1b8107
	    printf ("Loading file %s/%d\n", f->file, f->id);
Packit Service 1b8107
	if (FT_New_Face (_XftFTlibrary, f->file, f->id, &f->face))
Packit Service 1b8107
	    --f->lock;
Packit Service 1b8107
Packit Service 1b8107
	f->xsize = 0;
Packit Service 1b8107
	f->ysize = 0;
Packit Service 1b8107
	f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0;
Packit Service 1b8107
	_XftUncacheFiles ();
Packit Service 1b8107
    }
Packit Service 1b8107
    return f->face;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static void
Packit Service 1b8107
_XftLockError (const char *reason)
Packit Service 1b8107
{
Packit Service 1b8107
    fprintf (stderr, "Xft: locking error %s\n", reason);
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static void
Packit Service 1b8107
_XftUnlockFile (XftFtFile *f)
Packit Service 1b8107
{
Packit Service 1b8107
    if (--f->lock < 0)
Packit Service 1b8107
	_XftLockError ("too many file unlocks");
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
#define X_SIZE(face,i) ((face)->available_sizes[i].x_ppem)
Packit Service 1b8107
#define Y_SIZE(face,i) ((face)->available_sizes[i].y_ppem)
Packit Service 1b8107
Packit Service 1b8107
_X_HIDDEN FcBool
Packit Service 1b8107
_XftSetFace (XftFtFile *f, FT_F26Dot6 xsize, FT_F26Dot6 ysize, FT_Matrix *matrix)
Packit Service 1b8107
{
Packit Service 1b8107
    FT_Face face = f->face;
Packit Service 1b8107
Packit Service 1b8107
    if (f->xsize != xsize || f->ysize != ysize)
Packit Service 1b8107
    {
Packit Service 1b8107
	if (XftDebug() & XFT_DBG_GLYPH)
Packit Service 1b8107
	    printf ("Set face size to %dx%d (%dx%d)\n",
Packit Service 1b8107
		    (int) (xsize >> 6), (int) (ysize >> 6), (int) xsize, (int) ysize);
Packit Service 1b8107
	/*
Packit Service 1b8107
	 * Bitmap only faces must match exactly, so find the closest
Packit Service 1b8107
	 * one (height dominant search)
Packit Service 1b8107
	 */
Packit Service 1b8107
	if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
Packit Service 1b8107
	{
Packit Service 1b8107
	    int		i, best = 0;
Packit Service 1b8107
Packit Service 1b8107
#define xft_abs(a)	((a) < 0 ? -(a) : (a))
Packit Service 1b8107
#define dist(a,b)	(xft_abs((a)-(b)))
Packit Service 1b8107
Packit Service 1b8107
	    for (i = 1; i < face->num_fixed_sizes; i++)
Packit Service 1b8107
	    {
Packit Service 1b8107
		if (dist (ysize, Y_SIZE(face,i)) <
Packit Service 1b8107
		    dist (ysize, Y_SIZE(face, best)) ||
Packit Service 1b8107
		    (dist (ysize, Y_SIZE(face, i)) ==
Packit Service 1b8107
		     dist (ysize, Y_SIZE(face, best)) &&
Packit Service 1b8107
		     dist (xsize, X_SIZE(face, i)) <
Packit Service 1b8107
		     dist (xsize, X_SIZE(face, best))))
Packit Service 1b8107
		{
Packit Service 1b8107
		    best = i;
Packit Service 1b8107
		}
Packit Service 1b8107
	    }
Packit Service 1b8107
	    /*
Packit Service 1b8107
	     * Freetype 2.1.7 and earlier used width/height
Packit Service 1b8107
	     * for matching sizes in the BDF and PCF loaders.
Packit Service 1b8107
	     * This has been fixed for 2.1.8.  Because BDF and PCF
Packit Service 1b8107
	     * files have but a single strike per file, we can
Packit Service 1b8107
	     * simply try both sizes.
Packit Service 1b8107
	     */
Packit Service 1b8107
	    if (FT_Set_Char_Size (face, face->available_sizes[best].x_ppem,
Packit Service 1b8107
				  face->available_sizes[best].y_ppem, 0, 0) != 0
Packit Service 1b8107
		&&
Packit Service 1b8107
		FT_Set_Char_Size (face, face->available_sizes[best].width << 6,
Packit Service 1b8107
				  face->available_sizes[best].height << 6,
Packit Service 1b8107
				  0, 0) != 0)
Packit Service 1b8107
	    {
Packit Service 1b8107
		return False;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
	else
Packit Service 1b8107
    	{
Packit Service 1b8107
	    if (FT_Set_Char_Size (face, xsize, ysize, 0, 0))
Packit Service 1b8107
	    {
Packit Service 1b8107
		return False;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
	f->xsize = xsize;
Packit Service 1b8107
	f->ysize = ysize;
Packit Service 1b8107
    }
Packit Service 1b8107
    if (!FT_Matrix_Equal (&f->matrix, matrix))
Packit Service 1b8107
    {
Packit Service 1b8107
	if (XftDebug() & XFT_DBG_GLYPH)
Packit Service 1b8107
	    printf ("Set face matrix to (%g,%g,%g,%g)\n",
Packit Service 1b8107
		    (double) matrix->xx / 0x10000,
Packit Service 1b8107
		    (double) matrix->xy / 0x10000,
Packit Service 1b8107
		    (double) matrix->yx / 0x10000,
Packit Service 1b8107
		    (double) matrix->yy / 0x10000);
Packit Service 1b8107
	FT_Set_Transform (face, matrix, NULL);
Packit Service 1b8107
	f->matrix = *matrix;
Packit Service 1b8107
    }
Packit Service 1b8107
    return True;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static void
Packit Service 1b8107
_XftReleaseFile (XftFtFile *f)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFtFile	**prev;
Packit Service 1b8107
Packit Service 1b8107
    if (--f->ref != 0)
Packit Service 1b8107
        return;
Packit Service 1b8107
    if (f->lock)
Packit Service 1b8107
	_XftLockError ("Attempt to close locked file");
Packit Service 1b8107
    if (f->file)
Packit Service 1b8107
    {
Packit Service 1b8107
	for (prev = &_XftFtFiles; *prev; prev = &(*prev)->next)
Packit Service 1b8107
	{
Packit Service 1b8107
	    if (*prev == f)
Packit Service 1b8107
	    {
Packit Service 1b8107
		*prev = f->next;
Packit Service 1b8107
		break;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
	if (f->face)
Packit Service 1b8107
	    FT_Done_Face (f->face);
Packit Service 1b8107
    }
Packit Service 1b8107
    XftMemFree (XFT_MEM_FILE,
Packit Service 1b8107
		sizeof (XftFtFile) + (f->file ? strlen (f->file) + 1 : 0));
Packit Service 1b8107
    free (f);
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
/*
Packit Service 1b8107
 * Find a prime larger than the minimum reasonable hash size
Packit Service 1b8107
 */
Packit Service 1b8107
Packit Service 1b8107
static FcChar32
Packit Service 1b8107
_XftSqrt (FcChar32 a)
Packit Service 1b8107
{
Packit Service 1b8107
    FcChar32	    l, h, m;
Packit Service 1b8107
Packit Service 1b8107
    l = 2;
Packit Service 1b8107
    h = a/2;
Packit Service 1b8107
    while ((h-l) > 1)
Packit Service 1b8107
    {
Packit Service 1b8107
	m = (h+l) >> 1;
Packit Service 1b8107
	if (m * m < a)
Packit Service 1b8107
	    l = m;
Packit Service 1b8107
	else
Packit Service 1b8107
	    h = m;
Packit Service 1b8107
    }
Packit Service 1b8107
    return h;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static FcBool
Packit Service 1b8107
_XftIsPrime (FcChar32 i)
Packit Service 1b8107
{
Packit Service 1b8107
    FcChar32	l, t;
Packit Service 1b8107
Packit Service 1b8107
    if (i < 2)
Packit Service 1b8107
	return FcFalse;
Packit Service 1b8107
    if ((i & 1) == 0)
Packit Service 1b8107
    {
Packit Service 1b8107
	if (i == 2)
Packit Service 1b8107
	    return FcTrue;
Packit Service 1b8107
	return FcFalse;
Packit Service 1b8107
    }
Packit Service 1b8107
    l = _XftSqrt (i) + 1;
Packit Service 1b8107
    for (t = 3; t <= l; t += 2)
Packit Service 1b8107
	if (i % t == 0)
Packit Service 1b8107
	    return FcFalse;
Packit Service 1b8107
    return FcTrue;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static FcChar32
Packit Service 1b8107
_XftHashSize (FcChar32 num_unicode)
Packit Service 1b8107
{
Packit Service 1b8107
    /* at least 31.25 % extra space */
Packit Service 1b8107
    FcChar32	hash = num_unicode + (num_unicode >> 2) + (num_unicode >> 4);
Packit Service 1b8107
Packit Service 1b8107
    if ((hash & 1) == 0)
Packit Service 1b8107
	hash++;
Packit Service 1b8107
    while (!_XftIsPrime (hash))
Packit Service 1b8107
	hash += 2;
Packit Service 1b8107
    return hash;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT FT_Face
Packit Service 1b8107
XftLockFace (XftFont *public)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFontInt	*font = (XftFontInt *) public;
Packit Service 1b8107
    XftFontInfo	*fi = &font->info;
Packit Service 1b8107
    FT_Face	face;
Packit Service 1b8107
Packit Service 1b8107
    face = _XftLockFile (fi->file);
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Make sure the face is usable at the requested size
Packit Service 1b8107
     */
Packit Service 1b8107
    if (face && !_XftSetFace (fi->file, fi->xsize, fi->ysize, &fi->matrix))
Packit Service 1b8107
    {
Packit Service 1b8107
	_XftUnlockFile (fi->file);
Packit Service 1b8107
	face = NULL;
Packit Service 1b8107
    }
Packit Service 1b8107
    return face;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT void
Packit Service 1b8107
XftUnlockFace (XftFont *public)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFontInt	*font = (XftFontInt *) public;
Packit Service 1b8107
    _XftUnlockFile (font->info.file);
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static FcBool
Packit Service 1b8107
XftFontInfoFill (Display *dpy, _Xconst FcPattern *pattern, XftFontInfo *fi)
Packit Service 1b8107
{
Packit Service 1b8107
    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, True);
Packit Service 1b8107
    FcChar8	    *filename;
Packit Service 1b8107
    int		    id;
Packit Service 1b8107
    double	    dsize;
Packit Service 1b8107
    double	    aspect;
Packit Service 1b8107
    FcMatrix	    *font_matrix;
Packit Service 1b8107
    FcBool	    hinting, vertical_layout, autohint, global_advance;
Packit Service 1b8107
    int             hint_style;
Packit Service 1b8107
    FcChar32	    hash, *hashp;
Packit Service 1b8107
    FT_Face	    face;
Packit Service 1b8107
    int		    nhash;
Packit Service 1b8107
    FcBool	    bitmap;
Packit Service 1b8107
Packit Service 1b8107
    if (!info)
Packit Service 1b8107
	return FcFalse;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Initialize the whole XftFontInfo so that padding doesn't interfere with
Packit Service 1b8107
     * hash or XftFontInfoEqual().
Packit Service 1b8107
     */
Packit Service 1b8107
Packit Service 1b8107
    memset (fi, '\0', sizeof(*fi));
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Find the associated file
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetString (pattern, FC_FILE, 0, &filename)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	filename = NULL;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail0;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    switch (FcPatternGetInteger (pattern, FC_INDEX, 0, &id)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	id = 0;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail0;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    if (filename)
Packit Service 1b8107
	fi->file = _XftGetFile (filename, id);
Packit Service 1b8107
    else if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &face) == FcResultMatch
Packit Service 1b8107
	     && face)
Packit Service 1b8107
	fi->file = _XftGetFaceFile (face);
Packit Service 1b8107
    if (!fi->file)
Packit Service 1b8107
        goto bail0;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Compute pixel size
Packit Service 1b8107
     */
Packit Service 1b8107
    if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &dsize) != FcResultMatch)
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
Packit Service 1b8107
    if (FcPatternGetDouble (pattern, FC_ASPECT, 0, &aspect) != FcResultMatch)
Packit Service 1b8107
	aspect = 1.0;
Packit Service 1b8107
Packit Service 1b8107
    fi->ysize = (FT_F26Dot6) (dsize * 64.0);
Packit Service 1b8107
    fi->xsize = (FT_F26Dot6) (dsize * aspect * 64.0);
Packit Service 1b8107
Packit Service 1b8107
    if (XftDebug() & XFT_DBG_OPEN)
Packit Service 1b8107
	printf ("XftFontInfoFill: %s: %d (%g pixels)\n",
Packit Service 1b8107
		(filename ? filename : (FcChar8 *) "<none>"), id, dsize);
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get antialias value
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &fi->antialias)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->antialias = True;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get rgba value
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetInteger (pattern, FC_RGBA, 0, &fi->rgba)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->rgba = FC_RGBA_UNKNOWN;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get lcd_filter value
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetInteger (pattern, FC_LCD_FILTER, 0, &fi->lcd_filter)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->lcd_filter = FC_LCD_DEFAULT;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get matrix and transform values
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetMatrix (pattern, FC_MATRIX, 0, &font_matrix)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->matrix.xx = fi->matrix.yy = 0x10000;
Packit Service 1b8107
	fi->matrix.xy = fi->matrix.yx = 0;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	fi->matrix.xx = 0x10000L * font_matrix->xx;
Packit Service 1b8107
	fi->matrix.yy = 0x10000L * font_matrix->yy;
Packit Service 1b8107
	fi->matrix.xy = 0x10000L * font_matrix->xy;
Packit Service 1b8107
	fi->matrix.yx = 0x10000L * font_matrix->yx;
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    fi->transform = (fi->matrix.xx != 0x10000 || fi->matrix.xy != 0 ||
Packit Service 1b8107
		     fi->matrix.yx != 0 || fi->matrix.yy != 0x10000);
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get render value, set to false if no Render extension present
Packit Service 1b8107
     */
Packit Service 1b8107
    if (info->hasRender)
Packit Service 1b8107
    {
Packit Service 1b8107
	switch (FcPatternGetBool (pattern, XFT_RENDER, 0, &fi->render)) {
Packit Service 1b8107
	case FcResultNoMatch:
Packit Service 1b8107
	    fi->render = info->hasRender;
Packit Service 1b8107
	    break;
Packit Service 1b8107
	case FcResultMatch:
Packit Service 1b8107
	    break;
Packit Service 1b8107
	default:
Packit Service 1b8107
	    goto bail1;
Packit Service 1b8107
	}
Packit Service 1b8107
    }
Packit Service 1b8107
    else
Packit Service 1b8107
	fi->render = FcFalse;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Compute glyph load flags
Packit Service 1b8107
     */
Packit Service 1b8107
    fi->load_flags = FT_LOAD_DEFAULT;
Packit Service 1b8107
Packit Service 1b8107
#ifndef XFT_EMBEDDED_BITMAP
Packit Service 1b8107
#define XFT_EMBEDDED_BITMAP "embeddedbitmap"
Packit Service 1b8107
#endif
Packit Service 1b8107
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, XFT_EMBEDDED_BITMAP, 0, &bitmap)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	bitmap = FcFalse;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /* disable bitmaps when anti-aliasing or transforming glyphs */
Packit Service 1b8107
    if ((!bitmap && fi->antialias) || fi->transform)
Packit Service 1b8107
	fi->load_flags |= FT_LOAD_NO_BITMAP;
Packit Service 1b8107
Packit Service 1b8107
    /* disable hinting if requested */
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	hinting = FcTrue;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_EMBOLDEN, 0, &fi->embolden)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->embolden = FcFalse;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    switch (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	hint_style = FC_HINT_FULL;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    if (!hinting
Packit Service 1b8107
	|| hint_style == FC_HINT_NONE
Packit Service 1b8107
	)
Packit Service 1b8107
    {
Packit Service 1b8107
	fi->load_flags |= FT_LOAD_NO_HINTING;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /* Figure out the load target, which modifies the hinting
Packit Service 1b8107
     * behavior of FreeType based on the intended use of the glyphs.
Packit Service 1b8107
     */
Packit Service 1b8107
    if (fi->antialias)
Packit Service 1b8107
    {
Packit Service 1b8107
	if (FC_HINT_NONE < hint_style && hint_style < FC_HINT_FULL)
Packit Service 1b8107
	{
Packit Service 1b8107
	    fi->load_flags |= FT_LOAD_TARGET_LIGHT;
Packit Service 1b8107
	}
Packit Service 1b8107
	else
Packit Service 1b8107
	{
Packit Service 1b8107
	    /* autohinter will snap stems to integer widths, when
Packit Service 1b8107
	     * the LCD targets are used.
Packit Service 1b8107
	     */
Packit Service 1b8107
	    switch (fi->rgba) {
Packit Service 1b8107
	    case FC_RGBA_RGB:
Packit Service 1b8107
	    case FC_RGBA_BGR:
Packit Service 1b8107
		fi->load_flags |= FT_LOAD_TARGET_LCD;
Packit Service 1b8107
		break;
Packit Service 1b8107
	    case FC_RGBA_VRGB:
Packit Service 1b8107
	    case FC_RGBA_VBGR:
Packit Service 1b8107
		fi->load_flags |= FT_LOAD_TARGET_LCD_V;
Packit Service 1b8107
		break;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
    }
Packit Service 1b8107
    else
Packit Service 1b8107
	fi->load_flags |= FT_LOAD_TARGET_MONO;
Packit Service 1b8107
Packit Service 1b8107
    /* set vertical layout if requested */
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT, 0, &vertical_layout)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	vertical_layout = FcFalse;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    if (vertical_layout)
Packit Service 1b8107
	fi->load_flags |= FT_LOAD_VERTICAL_LAYOUT;
Packit Service 1b8107
Packit Service 1b8107
    /* force autohinting if requested */
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_AUTOHINT, 0, &autohint)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	autohint = FcFalse;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    if (autohint)
Packit Service 1b8107
	fi->load_flags |= FT_LOAD_FORCE_AUTOHINT;
Packit Service 1b8107
Packit Service 1b8107
    /* disable global advance width (for broken DynaLab TT CJK fonts) */
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_GLOBAL_ADVANCE, 0, &global_advance)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	global_advance = FcTrue;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    if (!global_advance)
Packit Service 1b8107
	fi->load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get requested spacing value
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetInteger (pattern, FC_SPACING, 0, &fi->spacing)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->spacing = FC_PROPORTIONAL;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Check for minspace
Packit Service 1b8107
     */
Packit Service 1b8107
Packit Service 1b8107
    switch (FcPatternGetBool (pattern, FC_MINSPACE, 0, &fi->minspace)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->minspace = FcFalse;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Check for fixed pixel spacing
Packit Service 1b8107
     */
Packit Service 1b8107
    switch (FcPatternGetInteger (pattern, FC_CHAR_WIDTH, 0, &fi->char_width)) {
Packit Service 1b8107
    case FcResultNoMatch:
Packit Service 1b8107
	fi->char_width = 0;
Packit Service 1b8107
	break;
Packit Service 1b8107
    case FcResultMatch:
Packit Service 1b8107
	if (fi->char_width)
Packit Service 1b8107
	    fi->spacing = FC_MONO;
Packit Service 1b8107
	break;
Packit Service 1b8107
    default:
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Step over hash value in the structure
Packit Service 1b8107
     */
Packit Service 1b8107
    hash = 0;
Packit Service 1b8107
    hashp = (FcChar32 *) fi + 1;
Packit Service 1b8107
    nhash = (sizeof (XftFontInfo) / sizeof (FcChar32)) - 1;
Packit Service 1b8107
Packit Service 1b8107
    while (nhash--)
Packit Service 1b8107
	hash += *hashp++;
Packit Service 1b8107
    fi->hash = hash;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * All done
Packit Service 1b8107
     */
Packit Service 1b8107
    return FcTrue;
Packit Service 1b8107
Packit Service 1b8107
bail1:
Packit Service 1b8107
    _XftReleaseFile (fi->file);
Packit Service 1b8107
    fi->file = NULL;
Packit Service 1b8107
bail0:
Packit Service 1b8107
    return FcFalse;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static void
Packit Service 1b8107
XftFontInfoEmpty (Display *dpy, XftFontInfo *fi)
Packit Service 1b8107
{
Packit Service 1b8107
    if (fi->file)
Packit Service 1b8107
	_XftReleaseFile (fi->file);
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
XftFontInfo *
Packit Service 1b8107
XftFontInfoCreate (Display *dpy, _Xconst FcPattern *pattern)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFontInfo	*fi = malloc (sizeof (XftFontInfo));
Packit Service 1b8107
Packit Service 1b8107
    if (!fi)
Packit Service 1b8107
	return NULL;
Packit Service 1b8107
Packit Service 1b8107
    if (!XftFontInfoFill (dpy, pattern, fi))
Packit Service 1b8107
    {
Packit Service 1b8107
	free (fi);
Packit Service 1b8107
	fi = NULL;
Packit Service 1b8107
    }
Packit Service 1b8107
    XftMemAlloc (XFT_MEM_FONT, sizeof (XftFontInfo));
Packit Service 1b8107
    return fi;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT void
Packit Service 1b8107
XftFontInfoDestroy (Display *dpy, XftFontInfo *fi)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFontInfoEmpty (dpy, fi);
Packit Service 1b8107
    XftMemFree (XFT_MEM_FONT, sizeof (XftFontInfo));
Packit Service 1b8107
    free (fi);
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT FcChar32
Packit Service 1b8107
XftFontInfoHash (_Xconst XftFontInfo *fi)
Packit Service 1b8107
{
Packit Service 1b8107
    return fi->hash;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT FcBool
Packit Service 1b8107
XftFontInfoEqual (_Xconst XftFontInfo *a, _Xconst XftFontInfo *b)
Packit Service 1b8107
{
Packit Service 1b8107
    return memcmp ((void *) a, (void *) b, sizeof (XftFontInfo)) == 0;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT XftFont *
Packit Service 1b8107
XftFontOpenInfo (Display	*dpy,
Packit Service 1b8107
		 FcPattern	*pattern,
Packit Service 1b8107
		 XftFontInfo	*fi)
Packit Service 1b8107
{
Packit Service 1b8107
    XftDisplayInfo	*info = _XftDisplayInfoGet (dpy, True);
Packit Service 1b8107
    FT_Face		face;
Packit Service 1b8107
    XftFont		**bucket;
Packit Service 1b8107
    XftFontInt		*font;
Packit Service 1b8107
    XRenderPictFormat	*format;
Packit Service 1b8107
    FcCharSet		*charset;
Packit Service 1b8107
    FcChar32		num_unicode;
Packit Service 1b8107
    FcChar32		hash_value;
Packit Service 1b8107
    FcChar32		rehash_value;
Packit Service 1b8107
    FcBool		antialias;
Packit Service 1b8107
    int			max_glyph_memory;
Packit Service 1b8107
    int			alloc_size;
Packit Service 1b8107
    int			ascent, descent, height;
Packit Service 1b8107
    int			i;
Packit Service 1b8107
    int			num_glyphs;
Packit Service 1b8107
Packit Service 1b8107
    if (!info)
Packit Service 1b8107
	return NULL;
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Find a matching previously opened font
Packit Service 1b8107
     */
Packit Service 1b8107
    bucket = &info->fontHash[fi->hash % XFT_NUM_FONT_HASH];
Packit Service 1b8107
    for (font = (XftFontInt *) *bucket; font; font = (XftFontInt *) font->hash_next)
Packit Service 1b8107
	if (XftFontInfoEqual (&font->info, fi))
Packit Service 1b8107
	{
Packit Service 1b8107
	    if (!font->ref++)
Packit Service 1b8107
		--info->num_unref_fonts;
Packit Service 1b8107
	    FcPatternDestroy (pattern);
Packit Service 1b8107
	    return &font->public;
Packit Service 1b8107
	}
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * No existing font, create another.
Packit Service 1b8107
     */
Packit Service 1b8107
Packit Service 1b8107
    if (XftDebug () & XFT_DBG_CACHE)
Packit Service 1b8107
	printf ("New font %s/%d size %dx%d\n",
Packit Service 1b8107
		fi->file->file, fi->file->id,
Packit Service 1b8107
		(int) fi->xsize >> 6, (int) fi->ysize >> 6);
Packit Service 1b8107
Packit Service 1b8107
    if (FcPatternGetInteger (pattern, XFT_MAX_GLYPH_MEMORY, 0,
Packit Service 1b8107
			     &max_glyph_memory) != FcResultMatch)
Packit Service 1b8107
	max_glyph_memory = XFT_FONT_MAX_GLYPH_MEMORY;
Packit Service 1b8107
Packit Service 1b8107
    face = _XftLockFile (fi->file);
Packit Service 1b8107
    if (!face)
Packit Service 1b8107
	goto bail0;
Packit Service 1b8107
Packit Service 1b8107
    if (!_XftSetFace (fi->file, fi->xsize, fi->ysize, &fi->matrix))
Packit Service 1b8107
	goto bail1;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Get the set of Unicode codepoints covered by the font.
Packit Service 1b8107
     * If the incoming pattern doesn't provide this data, go
Packit Service 1b8107
     * off and compute it.  Yes, this is expensive, but it's
Packit Service 1b8107
     * required to map Unicode to glyph indices.
Packit Service 1b8107
     */
Packit Service 1b8107
    if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) == FcResultMatch)
Packit Service 1b8107
	charset = FcCharSetCopy (charset);
Packit Service 1b8107
    else
Packit Service 1b8107
	charset = FcFreeTypeCharSet (face, FcConfigGetBlanks (NULL));
Packit Service 1b8107
Packit Service 1b8107
    antialias = fi->antialias;
Packit Service 1b8107
    if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
Packit Service 1b8107
	antialias = FcFalse;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Find the appropriate picture format
Packit Service 1b8107
     */
Packit Service 1b8107
    if (fi->render)
Packit Service 1b8107
    {
Packit Service 1b8107
	if (antialias)
Packit Service 1b8107
	{
Packit Service 1b8107
	    switch (fi->rgba) {
Packit Service 1b8107
	    case FC_RGBA_RGB:
Packit Service 1b8107
	    case FC_RGBA_BGR:
Packit Service 1b8107
	    case FC_RGBA_VRGB:
Packit Service 1b8107
	    case FC_RGBA_VBGR:
Packit Service 1b8107
		format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
Packit Service 1b8107
		break;
Packit Service 1b8107
	    default:
Packit Service 1b8107
		format = XRenderFindStandardFormat (dpy, PictStandardA8);
Packit Service 1b8107
		break;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
	else
Packit Service 1b8107
	{
Packit Service 1b8107
	    format = XRenderFindStandardFormat (dpy, PictStandardA1);
Packit Service 1b8107
	}
Packit Service 1b8107
Packit Service 1b8107
	if (!format)
Packit Service 1b8107
	    goto bail2;
Packit Service 1b8107
    }
Packit Service 1b8107
    else
Packit Service 1b8107
	format = NULL;
Packit Service 1b8107
Packit Service 1b8107
    if (charset)
Packit Service 1b8107
    {
Packit Service 1b8107
	num_unicode = FcCharSetCount (charset);
Packit Service 1b8107
	hash_value = _XftHashSize (num_unicode);
Packit Service 1b8107
	rehash_value = hash_value - 2;
Packit Service 1b8107
    }
Packit Service 1b8107
    else
Packit Service 1b8107
    {
Packit Service 1b8107
	num_unicode = 0;
Packit Service 1b8107
	hash_value = 0;
Packit Service 1b8107
	rehash_value = 0;
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Sometimes the glyphs are numbered 1..n, other times 0..n-1,
Packit Service 1b8107
     * accept either numbering scheme by making room in the table
Packit Service 1b8107
     */
Packit Service 1b8107
    num_glyphs = face->num_glyphs + 1;
Packit Service 1b8107
    alloc_size = (sizeof (XftFontInt) +
Packit Service 1b8107
		  num_glyphs * sizeof (XftGlyph *) +
Packit Service 1b8107
		  hash_value * sizeof (XftUcsHash));
Packit Service 1b8107
    font = malloc (alloc_size);
Packit Service 1b8107
Packit Service 1b8107
    if (!font)
Packit Service 1b8107
	goto bail2;
Packit Service 1b8107
Packit Service 1b8107
    XftMemAlloc (XFT_MEM_FONT, alloc_size);
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Public fields
Packit Service 1b8107
     */
Packit Service 1b8107
    if (fi->transform)
Packit Service 1b8107
    {
Packit Service 1b8107
	FT_Vector	vector;
Packit Service 1b8107
Packit Service 1b8107
	vector.x = 0;
Packit Service 1b8107
	vector.y = face->size->metrics.descender;
Packit Service 1b8107
	FT_Vector_Transform (&vector, &fi->matrix);
Packit Service 1b8107
	descent = -(vector.y >> 6);
Packit Service 1b8107
Packit Service 1b8107
	vector.x = 0;
Packit Service 1b8107
	vector.y = face->size->metrics.ascender;
Packit Service 1b8107
	FT_Vector_Transform (&vector, &fi->matrix);
Packit Service 1b8107
	ascent = vector.y >> 6;
Packit Service 1b8107
Packit Service 1b8107
	if (fi->minspace)
Packit Service 1b8107
	    height = ascent + descent;
Packit Service 1b8107
	else
Packit Service 1b8107
	{
Packit Service 1b8107
	    vector.x = 0;
Packit Service 1b8107
	    vector.y = face->size->metrics.height;
Packit Service 1b8107
	    FT_Vector_Transform (&vector, &fi->matrix);
Packit Service 1b8107
	    height = vector.y >> 6;
Packit Service 1b8107
	}
Packit Service 1b8107
    }
Packit Service 1b8107
    else
Packit Service 1b8107
    {
Packit Service 1b8107
	descent = -(face->size->metrics.descender >> 6);
Packit Service 1b8107
	ascent = face->size->metrics.ascender >> 6;
Packit Service 1b8107
	if (fi->minspace)
Packit Service 1b8107
	    height = ascent + descent;
Packit Service 1b8107
	else
Packit Service 1b8107
	    height = face->size->metrics.height >> 6;
Packit Service 1b8107
    }
Packit Service 1b8107
    font->public.ascent = ascent;
Packit Service 1b8107
    font->public.descent = descent;
Packit Service 1b8107
    font->public.height = height;
Packit Service 1b8107
Packit Service 1b8107
    if (fi->char_width)
Packit Service 1b8107
	font->public.max_advance_width = fi->char_width;
Packit Service 1b8107
    else
Packit Service 1b8107
    {
Packit Service 1b8107
	if (fi->transform)
Packit Service 1b8107
	{
Packit Service 1b8107
	    FT_Vector	vector;
Packit Service 1b8107
	    vector.x = face->size->metrics.max_advance;
Packit Service 1b8107
	    vector.y = 0;
Packit Service 1b8107
	    FT_Vector_Transform (&vector, &fi->matrix);
Packit Service 1b8107
	    font->public.max_advance_width = vector.x >> 6;
Packit Service 1b8107
	}
Packit Service 1b8107
	else
Packit Service 1b8107
	    font->public.max_advance_width = face->size->metrics.max_advance >> 6;
Packit Service 1b8107
    }
Packit Service 1b8107
    font->public.charset = charset;
Packit Service 1b8107
    font->public.pattern = pattern;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Management fields
Packit Service 1b8107
     */
Packit Service 1b8107
    font->ref = 1;
Packit Service 1b8107
Packit Service 1b8107
    font->next = info->fonts;
Packit Service 1b8107
    info->fonts = &font->public;
Packit Service 1b8107
Packit Service 1b8107
    font->hash_next = *bucket;
Packit Service 1b8107
    *bucket = &font->public;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Copy the info over
Packit Service 1b8107
     */
Packit Service 1b8107
    font->info = *fi;
Packit Service 1b8107
    /*
Packit Service 1b8107
     * reset the antialias field.  It can't
Packit Service 1b8107
     * be set correctly until the font is opened,
Packit Service 1b8107
     * which doesn't happen in XftFontInfoFill
Packit Service 1b8107
     */
Packit Service 1b8107
    font->info.antialias = antialias;
Packit Service 1b8107
    /*
Packit Service 1b8107
     * bump XftFile reference count
Packit Service 1b8107
     */
Packit Service 1b8107
    font->info.file->ref++;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Per glyph information
Packit Service 1b8107
     */
Packit Service 1b8107
    font->glyphs = (XftGlyph **) (font + 1);
Packit Service 1b8107
    memset (font->glyphs, '\0', num_glyphs * sizeof (XftGlyph *));
Packit Service 1b8107
    font->num_glyphs = num_glyphs;
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Unicode hash table information
Packit Service 1b8107
     */
Packit Service 1b8107
    font->hash_table = (XftUcsHash *) (font->glyphs + font->num_glyphs);
Packit Service 1b8107
    for (i = 0; i < hash_value; i++)
Packit Service 1b8107
    {
Packit Service 1b8107
	font->hash_table[i].ucs4 = ((FcChar32) ~0);
Packit Service 1b8107
	font->hash_table[i].glyph = 0;
Packit Service 1b8107
    }
Packit Service 1b8107
    font->hash_value = hash_value;
Packit Service 1b8107
    font->rehash_value = rehash_value;
Packit Service 1b8107
    /*
Packit Service 1b8107
     * X specific fields
Packit Service 1b8107
     */
Packit Service 1b8107
    font->glyphset = 0;
Packit Service 1b8107
    font->format = format;
Packit Service 1b8107
Packit Service 1b8107
    /*
Packit Service 1b8107
     * Glyph memory management fields
Packit Service 1b8107
     */
Packit Service 1b8107
    font->glyph_memory = 0;
Packit Service 1b8107
    font->max_glyph_memory = max_glyph_memory;
Packit Service 1b8107
    font->use_free_glyphs = info->use_free_glyphs;
Packit Service 1b8107
Packit Service 1b8107
    _XftUnlockFile (fi->file);
Packit Service 1b8107
Packit Service 1b8107
    return &font->public;
Packit Service 1b8107
Packit Service 1b8107
bail2:
Packit Service 1b8107
    FcCharSetDestroy (charset);
Packit Service 1b8107
bail1:
Packit Service 1b8107
    _XftUnlockFile (fi->file);
Packit Service 1b8107
bail0:
Packit Service 1b8107
    return NULL;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT XftFont *
Packit Service 1b8107
XftFontOpenPattern (Display *dpy, FcPattern *pattern)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFontInfo	    info;
Packit Service 1b8107
    XftFont	    *font;
Packit Service 1b8107
Packit Service 1b8107
    if (!XftFontInfoFill (dpy, pattern, &info))
Packit Service 1b8107
	return NULL;
Packit Service 1b8107
Packit Service 1b8107
    font = XftFontOpenInfo (dpy, pattern, &info;;
Packit Service 1b8107
    XftFontInfoEmpty (dpy, &info;;
Packit Service 1b8107
    return font;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT XftFont *
Packit Service 1b8107
XftFontCopy (Display *dpy, XftFont *public)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFontInt	    *font = (XftFontInt *) public;
Packit Service 1b8107
Packit Service 1b8107
    font->ref++;
Packit Service 1b8107
    return public;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static void
Packit Service 1b8107
XftFontDestroy (Display *dpy, XftFont *public)
Packit Service 1b8107
{
Packit Service 1b8107
    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
Packit Service 1b8107
    XftFontInt	    *font = (XftFontInt *) public;
Packit Service 1b8107
    int		    i;
Packit Service 1b8107
Packit Service 1b8107
    /* note reduction in memory use */
Packit Service 1b8107
    if (info)
Packit Service 1b8107
	info->glyph_memory -= font->glyph_memory;
Packit Service 1b8107
    /* Clean up the info */
Packit Service 1b8107
    XftFontInfoEmpty (dpy, &font->info);
Packit Service 1b8107
    /* Free the glyphset */
Packit Service 1b8107
    if (font->glyphset)
Packit Service 1b8107
	XRenderFreeGlyphSet (dpy, font->glyphset);
Packit Service 1b8107
    /* Free the glyphs */
Packit Service 1b8107
    for (i = 0; i < font->num_glyphs; i++)
Packit Service 1b8107
    {
Packit Service 1b8107
	XftGlyph	*xftg = font->glyphs[i];
Packit Service 1b8107
	if (xftg)
Packit Service 1b8107
	{
Packit Service 1b8107
	    if (xftg->bitmap)
Packit Service 1b8107
		free (xftg->bitmap);
Packit Service 1b8107
	    free (xftg);
Packit Service 1b8107
	}
Packit Service 1b8107
    }
Packit Service 1b8107
Packit Service 1b8107
    /* Free the pattern and the charset */
Packit Service 1b8107
    FcPatternDestroy (font->public.pattern);
Packit Service 1b8107
    FcCharSetDestroy (font->public.charset);
Packit Service 1b8107
Packit Service 1b8107
    /* Finally, free the font structure */
Packit Service 1b8107
    XftMemFree (XFT_MEM_FONT, sizeof (XftFontInt) +
Packit Service 1b8107
		font->num_glyphs * sizeof (XftGlyph *) +
Packit Service 1b8107
		font->hash_value * sizeof (XftUcsHash));
Packit Service 1b8107
    free (font);
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
static XftFont *
Packit Service 1b8107
XftFontFindNthUnref (XftDisplayInfo *info, int n)
Packit Service 1b8107
{
Packit Service 1b8107
    XftFont	*public;
Packit Service 1b8107
    XftFontInt	*font;
Packit Service 1b8107
Packit Service 1b8107
    for (public = info->fonts; public; public = font->next)
Packit Service 1b8107
    {
Packit Service 1b8107
	font = (XftFontInt*) public;
Packit Service 1b8107
	if (!font->ref && !n--)
Packit Service 1b8107
	    break;
Packit Service 1b8107
    }
Packit Service 1b8107
    return public;
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_HIDDEN void
Packit Service 1b8107
XftFontManageMemory (Display *dpy)
Packit Service 1b8107
{
Packit Service 1b8107
    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
Packit Service 1b8107
    XftFont	    **prev;
Packit Service 1b8107
    XftFont	    *public;
Packit Service 1b8107
    XftFontInt	    *font;
Packit Service 1b8107
Packit Service 1b8107
    if (!info)
Packit Service 1b8107
	return;
Packit Service 1b8107
    while (info->num_unref_fonts > info->max_unref_fonts)
Packit Service 1b8107
    {
Packit Service 1b8107
	public = XftFontFindNthUnref (info, rand() % info->num_unref_fonts);
Packit Service 1b8107
	font = (XftFontInt *) public;
Packit Service 1b8107
Packit Service 1b8107
	if (XftDebug () & XFT_DBG_CACHE)
Packit Service 1b8107
	    printf ("freeing unreferenced font %s/%d size %dx%d\n",
Packit Service 1b8107
		    font->info.file->file, font->info.file->id,
Packit Service 1b8107
		    (int) font->info.xsize >> 6, (int) font->info.ysize >> 6);
Packit Service 1b8107
Packit Service 1b8107
	/* Unhook from display list */
Packit Service 1b8107
	for (prev = &info->fonts; *prev; prev = &(*(XftFontInt **) prev)->next)
Packit Service 1b8107
	{
Packit Service 1b8107
	    if (*prev == public)
Packit Service 1b8107
	    {
Packit Service 1b8107
		*prev = font->next;
Packit Service 1b8107
		break;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
	/* Unhook from hash list */
Packit Service 1b8107
	for (prev = &info->fontHash[font->info.hash % XFT_NUM_FONT_HASH];
Packit Service 1b8107
	     *prev;
Packit Service 1b8107
	     prev = &(*(XftFontInt **) prev)->hash_next)
Packit Service 1b8107
	{
Packit Service 1b8107
	    if (*prev == public)
Packit Service 1b8107
	    {
Packit Service 1b8107
		*prev = font->hash_next;
Packit Service 1b8107
		break;
Packit Service 1b8107
	    }
Packit Service 1b8107
	}
Packit Service 1b8107
	/* Destroy the font */
Packit Service 1b8107
	XftFontDestroy (dpy, public);
Packit Service 1b8107
	--info->num_unref_fonts;
Packit Service 1b8107
    }
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT void
Packit Service 1b8107
XftFontClose (Display *dpy, XftFont *public)
Packit Service 1b8107
{
Packit Service 1b8107
    XftDisplayInfo  *info = _XftDisplayInfoGet (dpy, False);
Packit Service 1b8107
    XftFontInt	    *font = (XftFontInt *) public;
Packit Service 1b8107
Packit Service 1b8107
    if (--font->ref != 0)
Packit Service 1b8107
	return;
Packit Service 1b8107
Packit Service 1b8107
    if (info)
Packit Service 1b8107
    {
Packit Service 1b8107
	++info->num_unref_fonts;
Packit Service 1b8107
	XftFontManageMemory (dpy);
Packit Service 1b8107
    }
Packit Service 1b8107
    else
Packit Service 1b8107
    {
Packit Service 1b8107
	XftFontDestroy (dpy, public);
Packit Service 1b8107
    }
Packit Service 1b8107
}
Packit Service 1b8107
Packit Service 1b8107
_X_EXPORT FcBool
Packit Service 1b8107
XftInitFtLibrary (void)
Packit Service 1b8107
{
Packit Service 1b8107
    if (_XftFTlibrary)
Packit Service 1b8107
	return FcTrue;
Packit Service 1b8107
    if (FT_Init_FreeType (&_XftFTlibrary))
Packit Service 1b8107
	return FcFalse;
Packit Service 1b8107
    return FcTrue;
Packit Service 1b8107
}