xftextent.c revision c76ae52d
1c76ae52dSmrg/*
2c76ae52dSmrg * $Id: xftextent.c,v 1.1.1.1 2008/07/30 02:49:10 mrg Exp $
3c76ae52dSmrg *
4c76ae52dSmrg * Copyright © 2000 Keith Packard
5c76ae52dSmrg *
6c76ae52dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
7c76ae52dSmrg * documentation for any purpose is hereby granted without fee, provided that
8c76ae52dSmrg * the above copyright notice appear in all copies and that both that
9c76ae52dSmrg * copyright notice and this permission notice appear in supporting
10c76ae52dSmrg * documentation, and that the name of Keith Packard not be used in
11c76ae52dSmrg * advertising or publicity pertaining to distribution of the software without
12c76ae52dSmrg * specific, written prior permission.  Keith Packard makes no
13c76ae52dSmrg * representations about the suitability of this software for any purpose.  It
14c76ae52dSmrg * is provided "as is" without express or implied warranty.
15c76ae52dSmrg *
16c76ae52dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17c76ae52dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18c76ae52dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19c76ae52dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20c76ae52dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21c76ae52dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22c76ae52dSmrg * PERFORMANCE OF THIS SOFTWARE.
23c76ae52dSmrg */
24c76ae52dSmrg
25c76ae52dSmrg#include "xftint.h"
26c76ae52dSmrg
27c76ae52dSmrg_X_EXPORT void
28c76ae52dSmrgXftGlyphExtents (Display	    *dpy,
29c76ae52dSmrg		 XftFont	    *pub,
30c76ae52dSmrg		 _Xconst FT_UInt    *glyphs,
31c76ae52dSmrg		 int		    nglyphs,
32c76ae52dSmrg		 XGlyphInfo	    *extents)
33c76ae52dSmrg{
34c76ae52dSmrg    XftFontInt		*font = (XftFontInt *) pub;
35c76ae52dSmrg    FT_UInt		missing[XFT_NMISSING];
36c76ae52dSmrg    int			nmissing;
37c76ae52dSmrg    int			n;
38c76ae52dSmrg    _Xconst FT_UInt	*g;
39c76ae52dSmrg    FT_UInt		glyph;
40c76ae52dSmrg    XftGlyph		*xftg;
41c76ae52dSmrg    FcBool		glyphs_loaded;
42c76ae52dSmrg    int			x, y;
43c76ae52dSmrg    int			left, right, top, bottom;
44c76ae52dSmrg    int			overall_left, overall_right;
45c76ae52dSmrg    int			overall_top, overall_bottom;
46c76ae52dSmrg
47c76ae52dSmrg    g = glyphs;
48c76ae52dSmrg    n = nglyphs;
49c76ae52dSmrg    nmissing = 0;
50c76ae52dSmrg    glyphs_loaded = FcFalse;
51c76ae52dSmrg    while (n--)
52c76ae52dSmrg	if (XftFontCheckGlyph (dpy, pub, FcFalse, *g++, missing, &nmissing))
53c76ae52dSmrg	    glyphs_loaded = FcTrue;
54c76ae52dSmrg    if (nmissing)
55c76ae52dSmrg	XftFontLoadGlyphs (dpy, pub, FcFalse, missing, nmissing);
56c76ae52dSmrg    g = glyphs;
57c76ae52dSmrg    n = nglyphs;
58c76ae52dSmrg    xftg = 0;
59c76ae52dSmrg    while (n)
60c76ae52dSmrg    {
61c76ae52dSmrg	glyph = *g++;
62c76ae52dSmrg	n--;
63c76ae52dSmrg	if (glyph < font->num_glyphs &&
64c76ae52dSmrg	    (xftg = font->glyphs[glyph]))
65c76ae52dSmrg	    break;
66c76ae52dSmrg    }
67c76ae52dSmrg    if (n == 0)
68c76ae52dSmrg    {
69c76ae52dSmrg	if (xftg)
70c76ae52dSmrg	    *extents = xftg->metrics;
71c76ae52dSmrg	else
72c76ae52dSmrg	    memset (extents, '\0', sizeof (*extents));
73c76ae52dSmrg    }
74c76ae52dSmrg    else
75c76ae52dSmrg    {
76c76ae52dSmrg	x = 0;
77c76ae52dSmrg	y = 0;
78c76ae52dSmrg	overall_left = x - xftg->metrics.x;
79c76ae52dSmrg	overall_top = y - xftg->metrics.y;
80c76ae52dSmrg	overall_right = overall_left + (int) xftg->metrics.width;
81c76ae52dSmrg	overall_bottom = overall_top + (int) xftg->metrics.height;
82c76ae52dSmrg	x += xftg->metrics.xOff;
83c76ae52dSmrg	y += xftg->metrics.yOff;
84c76ae52dSmrg	while (n--)
85c76ae52dSmrg	{
86c76ae52dSmrg	    glyph = *g++;
87c76ae52dSmrg	    if (glyph < font->num_glyphs && (xftg = font->glyphs[glyph]))
88c76ae52dSmrg	    {
89c76ae52dSmrg		left = x - xftg->metrics.x;
90c76ae52dSmrg		top = y - xftg->metrics.y;
91c76ae52dSmrg		right = left + (int) xftg->metrics.width;
92c76ae52dSmrg		bottom = top + (int) xftg->metrics.height;
93c76ae52dSmrg		if (left < overall_left)
94c76ae52dSmrg		    overall_left = left;
95c76ae52dSmrg		if (top < overall_top)
96c76ae52dSmrg		    overall_top = top;
97c76ae52dSmrg		if (right > overall_right)
98c76ae52dSmrg		    overall_right = right;
99c76ae52dSmrg		if (bottom > overall_bottom)
100c76ae52dSmrg		    overall_bottom = bottom;
101c76ae52dSmrg		x += xftg->metrics.xOff;
102c76ae52dSmrg		y += xftg->metrics.yOff;
103c76ae52dSmrg	    }
104c76ae52dSmrg	}
105c76ae52dSmrg	extents->x = -overall_left;
106c76ae52dSmrg	extents->y = -overall_top;
107c76ae52dSmrg	extents->width = overall_right - overall_left;
108c76ae52dSmrg	extents->height = overall_bottom - overall_top;
109c76ae52dSmrg	extents->xOff = x;
110c76ae52dSmrg	extents->yOff = y;
111c76ae52dSmrg    }
112c76ae52dSmrg    if (glyphs_loaded)
113c76ae52dSmrg	_XftFontManageMemory (dpy, pub);
114c76ae52dSmrg}
115c76ae52dSmrg
116c76ae52dSmrg#define NUM_LOCAL   1024
117c76ae52dSmrg
118c76ae52dSmrg_X_EXPORT void
119c76ae52dSmrgXftTextExtents8 (Display	    *dpy,
120c76ae52dSmrg		 XftFont	    *pub,
121c76ae52dSmrg		 _Xconst FcChar8    *string,
122c76ae52dSmrg		 int		    len,
123c76ae52dSmrg		 XGlyphInfo	    *extents)
124c76ae52dSmrg{
125c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
126c76ae52dSmrg    int		    i;
127c76ae52dSmrg
128c76ae52dSmrg    if (len <= NUM_LOCAL)
129c76ae52dSmrg	glyphs = glyphs_local;
130c76ae52dSmrg    else
131c76ae52dSmrg    {
132c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
133c76ae52dSmrg	if (!glyphs)
134c76ae52dSmrg	{
135c76ae52dSmrg	    memset (extents, '\0', sizeof (XGlyphInfo));
136c76ae52dSmrg	    return;
137c76ae52dSmrg	}
138c76ae52dSmrg    }
139c76ae52dSmrg    for (i = 0; i < len; i++)
140c76ae52dSmrg	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
141c76ae52dSmrg    XftGlyphExtents (dpy, pub, glyphs, len, extents);
142c76ae52dSmrg    if (glyphs != glyphs_local)
143c76ae52dSmrg	free (glyphs);
144c76ae52dSmrg}
145c76ae52dSmrg
146c76ae52dSmrg_X_EXPORT void
147c76ae52dSmrgXftTextExtents16 (Display	    *dpy,
148c76ae52dSmrg		  XftFont	    *pub,
149c76ae52dSmrg		  _Xconst FcChar16  *string,
150c76ae52dSmrg		  int		    len,
151c76ae52dSmrg		  XGlyphInfo	    *extents)
152c76ae52dSmrg{
153c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
154c76ae52dSmrg    int		    i;
155c76ae52dSmrg
156c76ae52dSmrg    if (len <= NUM_LOCAL)
157c76ae52dSmrg	glyphs = glyphs_local;
158c76ae52dSmrg    else
159c76ae52dSmrg    {
160c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
161c76ae52dSmrg	if (!glyphs)
162c76ae52dSmrg	{
163c76ae52dSmrg	    memset (extents, '\0', sizeof (XGlyphInfo));
164c76ae52dSmrg	    return;
165c76ae52dSmrg	}
166c76ae52dSmrg    }
167c76ae52dSmrg    for (i = 0; i < len; i++)
168c76ae52dSmrg	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
169c76ae52dSmrg    XftGlyphExtents (dpy, pub, glyphs, len, extents);
170c76ae52dSmrg    if (glyphs != glyphs_local)
171c76ae52dSmrg	free (glyphs);
172c76ae52dSmrg}
173c76ae52dSmrg
174c76ae52dSmrg_X_EXPORT void
175c76ae52dSmrgXftTextExtents32 (Display	    *dpy,
176c76ae52dSmrg		  XftFont	    *pub,
177c76ae52dSmrg		  _Xconst FcChar32  *string,
178c76ae52dSmrg		  int		    len,
179c76ae52dSmrg		  XGlyphInfo	    *extents)
180c76ae52dSmrg{
181c76ae52dSmrg    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
182c76ae52dSmrg    int		    i;
183c76ae52dSmrg
184c76ae52dSmrg    if (len <= NUM_LOCAL)
185c76ae52dSmrg	glyphs = glyphs_local;
186c76ae52dSmrg    else
187c76ae52dSmrg    {
188c76ae52dSmrg	glyphs = malloc (len * sizeof (FT_UInt));
189c76ae52dSmrg	if (!glyphs)
190c76ae52dSmrg	{
191c76ae52dSmrg	    memset (extents, '\0', sizeof (XGlyphInfo));
192c76ae52dSmrg	    return;
193c76ae52dSmrg	}
194c76ae52dSmrg    }
195c76ae52dSmrg    for (i = 0; i < len; i++)
196c76ae52dSmrg	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
197c76ae52dSmrg    XftGlyphExtents (dpy, pub, glyphs, len, extents);
198c76ae52dSmrg    if (glyphs != glyphs_local)
199c76ae52dSmrg	free (glyphs);
200c76ae52dSmrg}
201c76ae52dSmrg
202c76ae52dSmrg_X_EXPORT void
203c76ae52dSmrgXftTextExtentsUtf8 (Display	    *dpy,
204c76ae52dSmrg		    XftFont	    *pub,
205c76ae52dSmrg		    _Xconst FcChar8 *string,
206c76ae52dSmrg		    int		    len,
207c76ae52dSmrg		    XGlyphInfo	    *extents)
208c76ae52dSmrg{
209c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
210c76ae52dSmrg    FcChar32	    ucs4;
211c76ae52dSmrg    int		    i;
212c76ae52dSmrg    int		    l;
213c76ae52dSmrg    int		    size;
214c76ae52dSmrg
215c76ae52dSmrg    i = 0;
216c76ae52dSmrg    glyphs = glyphs_local;
217c76ae52dSmrg    size = NUM_LOCAL;
218c76ae52dSmrg    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
219c76ae52dSmrg    {
220c76ae52dSmrg	if (i == size)
221c76ae52dSmrg	{
222c76ae52dSmrg	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
223c76ae52dSmrg	    if (!glyphs_new)
224c76ae52dSmrg	    {
225c76ae52dSmrg		if (glyphs != glyphs_local)
226c76ae52dSmrg		    free (glyphs);
227c76ae52dSmrg		memset (extents, '\0', sizeof (XGlyphInfo));
228c76ae52dSmrg		return;
229c76ae52dSmrg	    }
230c76ae52dSmrg	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
231c76ae52dSmrg	    size *= 2;
232c76ae52dSmrg	    if (glyphs != glyphs_local)
233c76ae52dSmrg		free (glyphs);
234c76ae52dSmrg	    glyphs = glyphs_new;
235c76ae52dSmrg	}
236c76ae52dSmrg	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
237c76ae52dSmrg	string += l;
238c76ae52dSmrg	len -= l;
239c76ae52dSmrg    }
240c76ae52dSmrg    XftGlyphExtents (dpy, pub, glyphs, i, extents);
241c76ae52dSmrg    if (glyphs != glyphs_local)
242c76ae52dSmrg	free (glyphs);
243c76ae52dSmrg}
244c76ae52dSmrg
245c76ae52dSmrg_X_EXPORT void
246c76ae52dSmrgXftTextExtentsUtf16 (Display		*dpy,
247c76ae52dSmrg		     XftFont		*pub,
248c76ae52dSmrg		     _Xconst FcChar8	*string,
249c76ae52dSmrg		     FcEndian		endian,
250c76ae52dSmrg		     int		len,
251c76ae52dSmrg		     XGlyphInfo		*extents)
252c76ae52dSmrg{
253c76ae52dSmrg    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
254c76ae52dSmrg    FcChar32	    ucs4;
255c76ae52dSmrg    int		    i;
256c76ae52dSmrg    int		    l;
257c76ae52dSmrg    int		    size;
258c76ae52dSmrg
259c76ae52dSmrg    i = 0;
260c76ae52dSmrg    glyphs = glyphs_local;
261c76ae52dSmrg    size = NUM_LOCAL;
262c76ae52dSmrg    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
263c76ae52dSmrg    {
264c76ae52dSmrg	if (i == size)
265c76ae52dSmrg	{
266c76ae52dSmrg	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
267c76ae52dSmrg	    if (!glyphs_new)
268c76ae52dSmrg	    {
269c76ae52dSmrg		if (glyphs != glyphs_local)
270c76ae52dSmrg		    free (glyphs);
271c76ae52dSmrg		memset (extents, '\0', sizeof (XGlyphInfo));
272c76ae52dSmrg		return;
273c76ae52dSmrg	    }
274c76ae52dSmrg	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
275c76ae52dSmrg	    size *= 2;
276c76ae52dSmrg	    if (glyphs != glyphs_local)
277c76ae52dSmrg		free (glyphs);
278c76ae52dSmrg	    glyphs = glyphs_new;
279c76ae52dSmrg	}
280c76ae52dSmrg	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
281c76ae52dSmrg	string += l;
282c76ae52dSmrg	len -= l;
283c76ae52dSmrg    }
284c76ae52dSmrg    XftGlyphExtents (dpy, pub, glyphs, i, extents);
285c76ae52dSmrg    if (glyphs != glyphs_local)
286c76ae52dSmrg	free (glyphs);
287c76ae52dSmrg}
288