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