xftextent.c revision 0d590c07
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 = -overall_left;
104	extents->y = -overall_top;
105	extents->width = overall_right - overall_left;
106	extents->height = overall_bottom - overall_top;
107	extents->xOff = x;
108	extents->yOff = 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 <= NUM_LOCAL)
127	glyphs = glyphs_local;
128    else
129    {
130	glyphs = malloc (len * sizeof (FT_UInt));
131	if (!glyphs)
132	{
133	    memset (extents, '\0', sizeof (XGlyphInfo));
134	    return;
135	}
136    }
137    for (i = 0; i < len; i++)
138	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
139    XftGlyphExtents (dpy, pub, glyphs, len, extents);
140    if (glyphs != glyphs_local)
141	free (glyphs);
142}
143
144_X_EXPORT void
145XftTextExtents16 (Display	    *dpy,
146		  XftFont	    *pub,
147		  _Xconst FcChar16  *string,
148		  int		    len,
149		  XGlyphInfo	    *extents)
150{
151    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
152    int		    i;
153
154    if (len <= NUM_LOCAL)
155	glyphs = glyphs_local;
156    else
157    {
158	glyphs = malloc (len * sizeof (FT_UInt));
159	if (!glyphs)
160	{
161	    memset (extents, '\0', sizeof (XGlyphInfo));
162	    return;
163	}
164    }
165    for (i = 0; i < len; i++)
166	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
167    XftGlyphExtents (dpy, pub, glyphs, len, extents);
168    if (glyphs != glyphs_local)
169	free (glyphs);
170}
171
172_X_EXPORT void
173XftTextExtents32 (Display	    *dpy,
174		  XftFont	    *pub,
175		  _Xconst FcChar32  *string,
176		  int		    len,
177		  XGlyphInfo	    *extents)
178{
179    FT_UInt	    *glyphs, glyphs_local[NUM_LOCAL];
180    int		    i;
181
182    if (len <= NUM_LOCAL)
183	glyphs = glyphs_local;
184    else
185    {
186	glyphs = malloc (len * sizeof (FT_UInt));
187	if (!glyphs)
188	{
189	    memset (extents, '\0', sizeof (XGlyphInfo));
190	    return;
191	}
192    }
193    for (i = 0; i < len; i++)
194	glyphs[i] = XftCharIndex (dpy, pub, string[i]);
195    XftGlyphExtents (dpy, pub, glyphs, len, extents);
196    if (glyphs != glyphs_local)
197	free (glyphs);
198}
199
200_X_EXPORT void
201XftTextExtentsUtf8 (Display	    *dpy,
202		    XftFont	    *pub,
203		    _Xconst FcChar8 *string,
204		    int		    len,
205		    XGlyphInfo	    *extents)
206{
207    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
208    FcChar32	    ucs4;
209    int		    i;
210    int		    l;
211    int		    size;
212
213    i = 0;
214    glyphs = glyphs_local;
215    size = NUM_LOCAL;
216    while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0)
217    {
218	if (i == size)
219	{
220	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
221	    if (!glyphs_new)
222	    {
223		if (glyphs != glyphs_local)
224		    free (glyphs);
225		memset (extents, '\0', sizeof (XGlyphInfo));
226		return;
227	    }
228	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
229	    size *= 2;
230	    if (glyphs != glyphs_local)
231		free (glyphs);
232	    glyphs = glyphs_new;
233	}
234	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
235	string += l;
236	len -= l;
237    }
238    XftGlyphExtents (dpy, pub, glyphs, i, extents);
239    if (glyphs != glyphs_local)
240	free (glyphs);
241}
242
243_X_EXPORT void
244XftTextExtentsUtf16 (Display		*dpy,
245		     XftFont		*pub,
246		     _Xconst FcChar8	*string,
247		     FcEndian		endian,
248		     int		len,
249		     XGlyphInfo		*extents)
250{
251    FT_UInt	    *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL];
252    FcChar32	    ucs4;
253    int		    i;
254    int		    l;
255    int		    size;
256
257    i = 0;
258    glyphs = glyphs_local;
259    size = NUM_LOCAL;
260    while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0)
261    {
262	if (i == size)
263	{
264	    glyphs_new = malloc (size * 2 * sizeof (FT_UInt));
265	    if (!glyphs_new)
266	    {
267		if (glyphs != glyphs_local)
268		    free (glyphs);
269		memset (extents, '\0', sizeof (XGlyphInfo));
270		return;
271	    }
272	    memcpy (glyphs_new, glyphs, size * sizeof (FT_UInt));
273	    size *= 2;
274	    if (glyphs != glyphs_local)
275		free (glyphs);
276	    glyphs = glyphs_new;
277	}
278	glyphs[i++] = XftCharIndex (dpy, pub, ucs4);
279	string += l;
280	len -= l;
281    }
282    XftGlyphExtents (dpy, pub, glyphs, i, extents);
283    if (glyphs != glyphs_local)
284	free (glyphs);
285}
286