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