Home | History | Annotate | Line # | Download | only in src
      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
     26 XftGlyphExtents (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
    117 XftTextExtents8 (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
    148 XftTextExtents16 (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
    179 XftTextExtents32 (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
    210 XftTextExtentsUtf8 (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
    256 XftTextExtentsUtf16 (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