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