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