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
XftGlyphExtents(Display * dpy,XftFont * pub,_Xconst FT_UInt * glyphs,int nglyphs,XGlyphInfo * extents)26 XftGlyphExtents (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
XftTextExtents8(Display * dpy,XftFont * pub,_Xconst FcChar8 * string,int len,XGlyphInfo * extents)117 XftTextExtents8 (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 ((size_t)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
XftTextExtents16(Display * dpy,XftFont * pub,_Xconst FcChar16 * string,int len,XGlyphInfo * extents)145 XftTextExtents16 (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 ((size_t)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
XftTextExtents32(Display * dpy,XftFont * pub,_Xconst FcChar32 * string,int len,XGlyphInfo * extents)173 XftTextExtents32 (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 ((size_t)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
XftTextExtentsUtf8(Display * dpy,XftFont * pub,_Xconst FcChar8 * string,int len,XGlyphInfo * extents)201 XftTextExtentsUtf8 (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_t)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_t)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
XftTextExtentsUtf16(Display * dpy,XftFont * pub,_Xconst FcChar8 * string,FcEndian endian,int len,XGlyphInfo * extents)244 XftTextExtentsUtf16 (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_t)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_t)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