Blame src/xftextent.c

Packit b749da
/*
Packit b749da
 * Copyright © 2000 Keith Packard
Packit b749da
 *
Packit b749da
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit b749da
 * documentation for any purpose is hereby granted without fee, provided that
Packit b749da
 * the above copyright notice appear in all copies and that both that
Packit b749da
 * copyright notice and this permission notice appear in supporting
Packit b749da
 * documentation, and that the name of Keith Packard not be used in
Packit b749da
 * advertising or publicity pertaining to distribution of the software without
Packit b749da
 * specific, written prior permission.  Keith Packard makes no
Packit b749da
 * representations about the suitability of this software for any purpose.  It
Packit b749da
 * is provided "as is" without express or implied warranty.
Packit b749da
 *
Packit b749da
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit b749da
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit b749da
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit b749da
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit b749da
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit b749da
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit b749da
 * PERFORMANCE OF THIS SOFTWARE.
Packit b749da
 */
Packit b749da
Packit b749da
#include "xftint.h"
Packit b749da
Packit b749da
_X_EXPORT void
Packit b749da
XftGlyphExtents (Display	    *dpy,
Packit b749da
		 XftFont	    *pub,
Packit b749da
		 _Xconst FT_UInt    *glyphs,
Packit b749da
		 int		    nglyphs,
Packit b749da
		 XGlyphInfo	    *extents)
Packit b749da
{
Packit b749da
    XftFontInt		*font = (XftFontInt *) pub;
Packit b749da
    FT_UInt		missing[XFT_NMISSING];
Packit b749da
    int			nmissing;
Packit b749da
    int			n;
Packit b749da
    _Xconst FT_UInt	*g;
Packit b749da
    FT_UInt		glyph;
Packit b749da
    XftGlyph		*xftg;
Packit b749da
    FcBool		glyphs_loaded;
Packit b749da
    int			x, y;
Packit b749da
    int			left, right, top, bottom;
Packit b749da
    int			overall_left, overall_right;
Packit b749da
    int			overall_top, overall_bottom;
Packit b749da
Packit b749da
    g = glyphs;
Packit b749da
    n = nglyphs;
Packit b749da
    nmissing = 0;
Packit b749da
    glyphs_loaded = FcFalse;
Packit b749da
    while (n--)
Packit b749da
	if (XftFontCheckGlyph (dpy, pub, FcFalse, *g++, missing, &nmissing))
Packit b749da
	    glyphs_loaded = FcTrue;
Packit b749da
    if (nmissing)
Packit b749da
	XftFontLoadGlyphs (dpy, pub, FcFalse, missing, nmissing);
Packit b749da
    g = glyphs;
Packit b749da
    n = nglyphs;
Packit b749da
    xftg = NULL;
Packit b749da
    while (n)
Packit b749da
    {
Packit b749da
	glyph = *g++;
Packit b749da
	n--;
Packit b749da
	if (glyph < font->num_glyphs &&
Packit b749da
	    (xftg = font->glyphs[glyph]))
Packit b749da
	    break;
Packit b749da
    }
Packit b749da
    if (n == 0)
Packit b749da
    {
Packit b749da
	if (xftg)
Packit b749da
	    *extents = xftg->metrics;
Packit b749da
	else
Packit b749da
	    memset (extents, '\0', sizeof (*extents));
Packit b749da
    }
Packit b749da
    else
Packit b749da
    {
Packit b749da
	x = 0;
Packit b749da
	y = 0;
Packit b749da
	overall_left = x - xftg->metrics.x;
Packit b749da
	overall_top = y - xftg->metrics.y;
Packit b749da
	overall_right = overall_left + (int) xftg->metrics.width;
Packit b749da
	overall_bottom = overall_top + (int) xftg->metrics.height;
Packit b749da
	x += xftg->metrics.xOff;
Packit b749da
	y += xftg->metrics.yOff;
Packit b749da
	while (n--)
Packit b749da
	{
Packit b749da
	    glyph = *g++;
Packit b749da
	    if (glyph < font->num_glyphs && (xftg = font->glyphs[glyph]))
Packit b749da
	    {
Packit b749da
		left = x - xftg->metrics.x;
Packit b749da
		top = y - xftg->metrics.y;
Packit b749da
		right = left + (int) xftg->metrics.width;
Packit b749da
		bottom = top + (int) xftg->metrics.height;
Packit b749da
		if (left < overall_left)
Packit b749da
		    overall_left = left;
Packit b749da
		if (top < overall_top)
Packit b749da
		    overall_top = top;
Packit b749da
		if (right > overall_right)
Packit b749da
		    overall_right = right;
Packit b749da
		if (bottom > overall_bottom)
Packit b749da
		    overall_bottom = bottom;
Packit b749da
		x += xftg->metrics.xOff;
Packit b749da
		y += xftg->metrics.yOff;
Packit b749da
	    }
Packit b749da
	}
Packit b749da
	extents->x = -overall_left;
Packit b749da
	extents->y = -overall_top;
Packit b749da
	extents->width = overall_right - overall_left;
Packit b749da
	extents->height = overall_bottom - overall_top;
Packit b749da
	extents->xOff = x;
Packit b749da
	extents->yOff = y;
Packit b749da
    }
Packit b749da
    if (glyphs_loaded)
Packit b749da
	_XftFontManageMemory (dpy, pub);
Packit b749da
}
Packit b749da
Packit b749da
#define NUM_LOCAL   1024
Packit b749da
Packit b749da
_X_EXPORT void
Packit b749da
XftTextExtents8 (Display	    *dpy,
Packit b749da
		 XftFont	    *pub,
Packit b749da
		 _Xconst FcChar8    *string,
Packit b749da
		 int		    len,
Packit b749da
		 XGlyphInfo	    *extents)
Packit b749da
{
Packit b749da
    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
Packit b749da
    int		    i;
Packit b749da
Packit b749da
    if (len <= NUM_LOCAL)
Packit b749da
	glyphs = glyphs_local;
Packit b749da
    else
Packit b749da
    {
Packit b749da
	glyphs = malloc (len * sizeof (FT_UInt));
Packit b749da
	if (!glyphs)
Packit b749da
	{
Packit b749da
	    memset (extents, '\0', sizeof (XGlyphInfo));
Packit b749da
	    return;
Packit b749da
	}
Packit b749da
    }
Packit b749da
    for (i = 0; i < len; i++)
Packit b749da
	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
Packit b749da
    XftGlyphExtents (dpy, pub, glyphs, len, extents);
Packit b749da
    if (glyphs != glyphs_local)
Packit b749da
	free (glyphs);
Packit b749da
}
Packit b749da
Packit b749da
_X_EXPORT void
Packit b749da
XftTextExtents16 (Display	    *dpy,
Packit b749da
		  XftFont	    *pub,
Packit b749da
		  _Xconst FcChar16  *string,
Packit b749da
		  int		    len,
Packit b749da
		  XGlyphInfo	    *extents)
Packit b749da
{
Packit b749da
    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
Packit b749da
    int		    i;
Packit b749da
Packit b749da
    if (len <= NUM_LOCAL)
Packit b749da
	glyphs = glyphs_local;
Packit b749da
    else
Packit b749da
    {
Packit b749da
	glyphs = malloc (len * sizeof (FT_UInt));
Packit b749da
	if (!glyphs)
Packit b749da
	{
Packit b749da
	    memset (extents, '\0', sizeof (XGlyphInfo));
Packit b749da
	    return;
Packit b749da
	}
Packit b749da
    }
Packit b749da
    for (i = 0; i < len; i++)
Packit b749da
	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
Packit b749da
    XftGlyphExtents (dpy, pub, glyphs, len, extents);
Packit b749da
    if (glyphs != glyphs_local)
Packit b749da
	free (glyphs);
Packit b749da
}
Packit b749da
Packit b749da
_X_EXPORT void
Packit b749da
XftTextExtents32 (Display	    *dpy,
Packit b749da
		  XftFont	    *pub,
Packit b749da
		  _Xconst FcChar32  *string,
Packit b749da
		  int		    len,
Packit b749da
		  XGlyphInfo	    *extents)
Packit b749da
{
Packit b749da
    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
Packit b749da
    int		    i;
Packit b749da
Packit b749da
    if (len <= NUM_LOCAL)
Packit b749da
	glyphs = glyphs_local;
Packit b749da
    else
Packit b749da
    {
Packit b749da
	glyphs = malloc (len * sizeof (FT_UInt));
Packit b749da
	if (!glyphs)
Packit b749da
	{
Packit b749da
	    memset (extents, '\0', sizeof (XGlyphInfo));
Packit b749da
	    return;
Packit b749da
	}
Packit b749da
    }
Packit b749da
    for (i = 0; i < len; i++)
Packit b749da
	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
Packit b749da
    XftGlyphExtents (dpy, pub, glyphs, len, extents);
Packit b749da
    if (glyphs != glyphs_local)
Packit b749da
	free (glyphs);
Packit b749da
}
Packit b749da
Packit b749da
_X_EXPORT void
Packit b749da
XftTextExtentsUtf8 (Display	    *dpy,
Packit b749da
		    XftFont	    *pub,
Packit b749da
		    _Xconst FcChar8 *string,
Packit b749da
		    int		    len,
Packit b749da
		    XGlyphInfo	    *extents)
Packit b749da
{
Packit b749da
    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
Packit b749da
    FcChar32	    ucs4;
Packit b749da
    int		    i;
Packit b749da
    int		    l;
Packit b749da
    int		    size;
Packit b749da
Packit b749da
    i = 0;
Packit b749da
    glyphs = glyphs_local;
Packit b749da
    size = NUM_LOCAL;
Packit b749da
    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
Packit b749da
    {
Packit b749da
	if (i == size)
Packit b749da
	{
Packit b749da
	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
Packit b749da
	    if (!glyphs_new)
Packit b749da
	    {
Packit b749da
		if (glyphs != glyphs_local)
Packit b749da
		    free (glyphs);
Packit b749da
		memset (extents, '\0', sizeof (XGlyphInfo));
Packit b749da
		return;
Packit b749da
	    }
Packit b749da
	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
Packit b749da
	    size *= 2;
Packit b749da
	    if (glyphs != glyphs_local)
Packit b749da
		free (glyphs);
Packit b749da
	    glyphs = glyphs_new;
Packit b749da
	}
Packit b749da
	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
Packit b749da
	string += l;
Packit b749da
	len -= l;
Packit b749da
    }
Packit b749da
    XftGlyphExtents (dpy, pub, glyphs, i, extents);
Packit b749da
    if (glyphs != glyphs_local)
Packit b749da
	free (glyphs);
Packit b749da
}
Packit b749da
Packit b749da
_X_EXPORT void
Packit b749da
XftTextExtentsUtf16 (Display		*dpy,
Packit b749da
		     XftFont		*pub,
Packit b749da
		     _Xconst FcChar8	*string,
Packit b749da
		     FcEndian		endian,
Packit b749da
		     int		len,
Packit b749da
		     XGlyphInfo		*extents)
Packit b749da
{
Packit b749da
    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
Packit b749da
    FcChar32	    ucs4;
Packit b749da
    int		    i;
Packit b749da
    int		    l;
Packit b749da
    int		    size;
Packit b749da
Packit b749da
    i = 0;
Packit b749da
    glyphs = glyphs_local;
Packit b749da
    size = NUM_LOCAL;
Packit b749da
    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
Packit b749da
    {
Packit b749da
	if (i == size)
Packit b749da
	{
Packit b749da
	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
Packit b749da
	    if (!glyphs_new)
Packit b749da
	    {
Packit b749da
		if (glyphs != glyphs_local)
Packit b749da
		    free (glyphs);
Packit b749da
		memset (extents, '\0', sizeof (XGlyphInfo));
Packit b749da
		return;
Packit b749da
	    }
Packit b749da
	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
Packit b749da
	    size *= 2;
Packit b749da
	    if (glyphs != glyphs_local)
Packit b749da
		free (glyphs);
Packit b749da
	    glyphs = glyphs_new;
Packit b749da
	}
Packit b749da
	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
Packit b749da
	string += l;
Packit b749da
	len -= l;
Packit b749da
    }
Packit b749da
    XftGlyphExtents (dpy, pub, glyphs, i, extents);
Packit b749da
    if (glyphs != glyphs_local)
Packit b749da
	free (glyphs);
Packit b749da
}