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