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 } 10384febdacSmrg extents->x = (short)(-overall_left); 10484febdacSmrg extents->y = (short)(-overall_top); 10584febdacSmrg extents->width = (unsigned short)(overall_right - overall_left); 10684febdacSmrg extents->height = (unsigned short)(overall_bottom - overall_top); 10784febdacSmrg extents->xOff = (short)x; 10884febdacSmrg extents->yOff = (short)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 1268a91a6ebSmrg if (len < 0) 127de3c0529Smrg return; 128de3c0529Smrg 129c76ae52dSmrg if (len <= NUM_LOCAL) 1308a91a6ebSmrg *(glyphs = glyphs_local) = 0; 131c76ae52dSmrg else 132c76ae52dSmrg { 133de3c0529Smrg glyphs = AllocUIntArray (len); 134c76ae52dSmrg if (!glyphs) 135c76ae52dSmrg { 136c76ae52dSmrg memset (extents, '\0', sizeof (XGlyphInfo)); 137c76ae52dSmrg return; 138c76ae52dSmrg } 139c76ae52dSmrg } 140c76ae52dSmrg for (i = 0; i < len; i++) 141c76ae52dSmrg glyphs[i] = XftCharIndex (dpy, pub, string[i]); 142c76ae52dSmrg XftGlyphExtents (dpy, pub, glyphs, len, extents); 143c76ae52dSmrg if (glyphs != glyphs_local) 144c76ae52dSmrg free (glyphs); 145c76ae52dSmrg} 146c76ae52dSmrg 147c76ae52dSmrg_X_EXPORT void 148c76ae52dSmrgXftTextExtents16 (Display *dpy, 149c76ae52dSmrg XftFont *pub, 1502836776bSmrg _Xconst FcChar16 *string, 151c76ae52dSmrg int len, 152c76ae52dSmrg XGlyphInfo *extents) 153c76ae52dSmrg{ 154c76ae52dSmrg FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 155c76ae52dSmrg int i; 156c76ae52dSmrg 1578a91a6ebSmrg if (len < 0) 158de3c0529Smrg return; 159de3c0529Smrg 160c76ae52dSmrg if (len <= NUM_LOCAL) 1618a91a6ebSmrg *(glyphs = glyphs_local) = 0; 162c76ae52dSmrg else 163c76ae52dSmrg { 164de3c0529Smrg glyphs = AllocUIntArray (len); 165c76ae52dSmrg if (!glyphs) 166c76ae52dSmrg { 167c76ae52dSmrg memset (extents, '\0', sizeof (XGlyphInfo)); 168c76ae52dSmrg return; 169c76ae52dSmrg } 170c76ae52dSmrg } 171c76ae52dSmrg for (i = 0; i < len; i++) 172c76ae52dSmrg glyphs[i] = XftCharIndex (dpy, pub, string[i]); 173c76ae52dSmrg XftGlyphExtents (dpy, pub, glyphs, len, extents); 174c76ae52dSmrg if (glyphs != glyphs_local) 175c76ae52dSmrg free (glyphs); 176c76ae52dSmrg} 177c76ae52dSmrg 178c76ae52dSmrg_X_EXPORT void 179c76ae52dSmrgXftTextExtents32 (Display *dpy, 180c76ae52dSmrg XftFont *pub, 1812836776bSmrg _Xconst FcChar32 *string, 182c76ae52dSmrg int len, 183c76ae52dSmrg XGlyphInfo *extents) 184c76ae52dSmrg{ 185c76ae52dSmrg FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 186c76ae52dSmrg int i; 187c76ae52dSmrg 1888a91a6ebSmrg if (len < 0) 189de3c0529Smrg return; 190de3c0529Smrg 191c76ae52dSmrg if (len <= NUM_LOCAL) 1928a91a6ebSmrg *(glyphs = glyphs_local) = 0; 193c76ae52dSmrg else 194c76ae52dSmrg { 195de3c0529Smrg glyphs = AllocUIntArray (len); 196c76ae52dSmrg if (!glyphs) 197c76ae52dSmrg { 198c76ae52dSmrg memset (extents, '\0', sizeof (XGlyphInfo)); 199c76ae52dSmrg return; 200c76ae52dSmrg } 201c76ae52dSmrg } 202c76ae52dSmrg for (i = 0; i < len; i++) 203c76ae52dSmrg glyphs[i] = XftCharIndex (dpy, pub, string[i]); 204c76ae52dSmrg XftGlyphExtents (dpy, pub, glyphs, len, extents); 205c76ae52dSmrg if (glyphs != glyphs_local) 206c76ae52dSmrg free (glyphs); 207c76ae52dSmrg} 208c76ae52dSmrg 209c76ae52dSmrg_X_EXPORT void 210c76ae52dSmrgXftTextExtentsUtf8 (Display *dpy, 211c76ae52dSmrg XftFont *pub, 2122836776bSmrg _Xconst FcChar8 *string, 213c76ae52dSmrg int len, 214c76ae52dSmrg XGlyphInfo *extents) 215c76ae52dSmrg{ 216c76ae52dSmrg FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; 217c76ae52dSmrg FcChar32 ucs4; 218c76ae52dSmrg int i; 219c76ae52dSmrg int l; 220c76ae52dSmrg int size; 221c76ae52dSmrg 2228a91a6ebSmrg if (len < 0) 223de3c0529Smrg return; 224de3c0529Smrg 225c76ae52dSmrg i = 0; 2268a91a6ebSmrg *(glyphs = glyphs_local) = 0; 227c76ae52dSmrg size = NUM_LOCAL; 228c76ae52dSmrg while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0) 229c76ae52dSmrg { 230c76ae52dSmrg if (i == size) 231c76ae52dSmrg { 232de3c0529Smrg glyphs_new = AllocUIntArray (size * 2); 233c76ae52dSmrg if (!glyphs_new) 234c76ae52dSmrg { 235c76ae52dSmrg if (glyphs != glyphs_local) 236c76ae52dSmrg free (glyphs); 237c76ae52dSmrg memset (extents, '\0', sizeof (XGlyphInfo)); 238c76ae52dSmrg return; 239c76ae52dSmrg } 24084febdacSmrg memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt)); 241c76ae52dSmrg size *= 2; 242c76ae52dSmrg if (glyphs != glyphs_local) 243c76ae52dSmrg free (glyphs); 244c76ae52dSmrg glyphs = glyphs_new; 245c76ae52dSmrg } 246c76ae52dSmrg glyphs[i++] = XftCharIndex (dpy, pub, ucs4); 247c76ae52dSmrg string += l; 248c76ae52dSmrg len -= l; 249c76ae52dSmrg } 250c76ae52dSmrg XftGlyphExtents (dpy, pub, glyphs, i, extents); 251c76ae52dSmrg if (glyphs != glyphs_local) 252c76ae52dSmrg free (glyphs); 253c76ae52dSmrg} 254c76ae52dSmrg 255c76ae52dSmrg_X_EXPORT void 256c76ae52dSmrgXftTextExtentsUtf16 (Display *dpy, 257c76ae52dSmrg XftFont *pub, 2582836776bSmrg _Xconst FcChar8 *string, 259c76ae52dSmrg FcEndian endian, 260c76ae52dSmrg int len, 261c76ae52dSmrg XGlyphInfo *extents) 262c76ae52dSmrg{ 263c76ae52dSmrg FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; 264c76ae52dSmrg FcChar32 ucs4; 265c76ae52dSmrg int i; 266c76ae52dSmrg int l; 267c76ae52dSmrg int size; 268c76ae52dSmrg 2698a91a6ebSmrg if (len < 0) 270de3c0529Smrg return; 271de3c0529Smrg 272c76ae52dSmrg i = 0; 2738a91a6ebSmrg *(glyphs = glyphs_local) = 0; 274c76ae52dSmrg size = NUM_LOCAL; 275c76ae52dSmrg while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0) 276c76ae52dSmrg { 277c76ae52dSmrg if (i == size) 278c76ae52dSmrg { 279de3c0529Smrg glyphs_new = AllocUIntArray (size * 2); 280c76ae52dSmrg if (!glyphs_new) 281c76ae52dSmrg { 282c76ae52dSmrg if (glyphs != glyphs_local) 283c76ae52dSmrg free (glyphs); 284c76ae52dSmrg memset (extents, '\0', sizeof (XGlyphInfo)); 285c76ae52dSmrg return; 286c76ae52dSmrg } 28784febdacSmrg memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt)); 288c76ae52dSmrg size *= 2; 289c76ae52dSmrg if (glyphs != glyphs_local) 290c76ae52dSmrg free (glyphs); 291c76ae52dSmrg glyphs = glyphs_new; 292c76ae52dSmrg } 293c76ae52dSmrg glyphs[i++] = XftCharIndex (dpy, pub, ucs4); 294c76ae52dSmrg string += l; 295c76ae52dSmrg len -= l; 296c76ae52dSmrg } 297c76ae52dSmrg XftGlyphExtents (dpy, pub, glyphs, i, extents); 298c76ae52dSmrg if (glyphs != glyphs_local) 299c76ae52dSmrg free (glyphs); 300c76ae52dSmrg} 301