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