|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Copyright © 2000 Keith Packard
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
Packit |
b749da |
* documentation for any purpose is hereby granted without fee, provided that
|
|
Packit |
b749da |
* the above copyright notice appear in all copies and that both that
|
|
Packit |
b749da |
* copyright notice and this permission notice appear in supporting
|
|
Packit |
b749da |
* documentation, and that the name of Keith Packard not be used in
|
|
Packit |
b749da |
* advertising or publicity pertaining to distribution of the software without
|
|
Packit |
b749da |
* specific, written prior permission. Keith Packard makes no
|
|
Packit |
b749da |
* representations about the suitability of this software for any purpose. It
|
|
Packit |
b749da |
* is provided "as is" without express or implied warranty.
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
Packit |
b749da |
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
Packit |
b749da |
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
Packit |
b749da |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
Packit |
b749da |
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
Packit |
b749da |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
Packit |
b749da |
* PERFORMANCE OF THIS SOFTWARE.
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
|
|
Packit |
b749da |
#include "xftint.h"
|
|
Packit |
b749da |
#include FT_OUTLINE_H
|
|
Packit |
b749da |
#include FT_LCD_FILTER_H
|
|
Packit |
b749da |
|
|
Packit |
b749da |
#include FT_SYNTHESIS_H
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Validate the memory info for a font
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
|
|
Packit |
b749da |
static void
|
|
Packit |
b749da |
_XftFontValidateMemory (Display *dpy, XftFont *public)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) public;
|
|
Packit |
b749da |
unsigned long glyph_memory;
|
|
Packit |
b749da |
FT_UInt glyphindex;
|
|
Packit |
b749da |
XftGlyph *xftg;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
glyph_memory = 0;
|
|
Packit |
b749da |
for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg = font->glyphs[glyphindex];
|
|
Packit |
b749da |
if (xftg)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
glyph_memory += xftg->glyph_memory;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
if (glyph_memory != font->glyph_memory)
|
|
Packit |
b749da |
printf ("Font glyph cache incorrect has %ld bytes, should have %ld\n",
|
|
Packit |
b749da |
font->glyph_memory, glyph_memory);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
|
|
Packit |
b749da |
* into a different format. For example, we want to convert a
|
|
Packit |
b749da |
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
|
|
Packit |
b749da |
* ARGB or ABGR bitmap.
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* this function prepares a target descriptor for this operation.
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* input :: target bitmap descriptor. The function will set its
|
|
Packit |
b749da |
* 'width', 'rows' and 'pitch' fields, and only these
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* slot :: the glyph slot containing the source bitmap. this
|
|
Packit |
b749da |
* function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* mode :: the requested final rendering mode. supported values are
|
|
Packit |
b749da |
* MONO, NORMAL (i.e. gray), LCD and LCD_V
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* the function returns the size in bytes of the corresponding buffer,
|
|
Packit |
b749da |
* it's up to the caller to allocate the corresponding memory block
|
|
Packit |
b749da |
* before calling _fill_xrender_bitmap
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* it also returns -1 in case of error (e.g. incompatible arguments,
|
|
Packit |
b749da |
* like trying to convert a gray bitmap into a monochrome one)
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
static int
|
|
Packit |
b749da |
_compute_xrender_bitmap_size( FT_Bitmap* target,
|
|
Packit |
b749da |
FT_GlyphSlot slot,
|
|
Packit |
b749da |
FT_Render_Mode mode )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
FT_Bitmap* ftbit;
|
|
Packit |
b749da |
int width, height, pitch;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
|
|
Packit |
b749da |
return -1;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
// compute the size of the final bitmap
|
|
Packit |
b749da |
ftbit = &slot->bitmap;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
width = ftbit->width;
|
|
Packit |
b749da |
height = ftbit->rows;
|
|
Packit |
b749da |
pitch = (width+3) & ~3;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
switch ( ftbit->pixel_mode )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
case FT_PIXEL_MODE_MONO:
|
|
Packit |
b749da |
if ( mode == FT_RENDER_MODE_MONO )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
pitch = (((width+31) & ~31) >> 3);
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
/* fall-through */
|
|
Packit |
b749da |
|
|
Packit |
b749da |
case FT_PIXEL_MODE_GRAY:
|
|
Packit |
b749da |
if ( mode == FT_RENDER_MODE_LCD ||
|
|
Packit |
b749da |
mode == FT_RENDER_MODE_LCD_V )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/* each pixel is replicated into a 32-bit ARGB value */
|
|
Packit |
b749da |
pitch = width*4;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
case FT_PIXEL_MODE_LCD:
|
|
Packit |
b749da |
if ( mode != FT_RENDER_MODE_LCD )
|
|
Packit |
b749da |
return -1;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/* horz pixel triplets are packed into 32-bit ARGB values */
|
|
Packit |
b749da |
width /= 3;
|
|
Packit |
b749da |
pitch = width*4;
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
case FT_PIXEL_MODE_LCD_V:
|
|
Packit |
b749da |
if ( mode != FT_RENDER_MODE_LCD_V )
|
|
Packit |
b749da |
return -1;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/* vert pixel triplets are packed into 32-bit ARGB values */
|
|
Packit |
b749da |
height /= 3;
|
|
Packit |
b749da |
pitch = width*4;
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
default: /* unsupported source format */
|
|
Packit |
b749da |
return -1;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
target->width = width;
|
|
Packit |
b749da |
target->rows = height;
|
|
Packit |
b749da |
target->pitch = pitch;
|
|
Packit |
b749da |
target->buffer = NULL;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
return pitch * height;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
|
|
Packit |
b749da |
* into a different format (see _compute_xrender_bitmap_size)
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* you should call this function after _compute_xrender_bitmap_size
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* target :: target bitmap descriptor. Note that its 'buffer' pointer
|
|
Packit |
b749da |
* must point to memory allocated by the caller
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* slot :: the glyph slot containing the source bitmap
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* mode :: the requested final rendering mode
|
|
Packit |
b749da |
*
|
|
Packit |
b749da |
* bgr :: boolean, set if BGR or VBGR pixel ordering is needed
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
static void
|
|
Packit |
b749da |
_fill_xrender_bitmap( FT_Bitmap* target,
|
|
Packit |
b749da |
FT_GlyphSlot slot,
|
|
Packit |
b749da |
FT_Render_Mode mode,
|
|
Packit |
b749da |
int bgr )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
FT_Bitmap* ftbit = &slot->bitmap;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned char* srcLine = ftbit->buffer;
|
|
Packit |
b749da |
unsigned char* dstLine = target->buffer;
|
|
Packit |
b749da |
int src_pitch = ftbit->pitch;
|
|
Packit |
b749da |
int width = target->width;
|
|
Packit |
b749da |
int height = target->rows;
|
|
Packit |
b749da |
int pitch = target->pitch;
|
|
Packit |
b749da |
int subpixel;
|
|
Packit |
b749da |
int h;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
subpixel = ( mode == FT_RENDER_MODE_LCD ||
|
|
Packit |
b749da |
mode == FT_RENDER_MODE_LCD_V );
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if ( src_pitch < 0 )
|
|
Packit |
b749da |
srcLine -= src_pitch*(ftbit->rows-1);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
switch ( ftbit->pixel_mode )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
case FT_PIXEL_MODE_MONO:
|
|
Packit |
b749da |
if ( subpixel ) /* convert mono to ARGB32 values */
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++ )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
|
|
Packit |
b749da |
((unsigned int*)dstLine)[x] = 0xffffffffU;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else if ( mode == FT_RENDER_MODE_NORMAL ) /* convert mono to 8-bit gray */
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++ )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
|
|
Packit |
b749da |
dstLine[x] = 0xff;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else /* copy mono to mono */
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int bytes = (width+7) >> 3;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
memcpy( dstLine, srcLine, bytes );
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
case FT_PIXEL_MODE_GRAY:
|
|
Packit |
b749da |
if ( subpixel ) /* convert gray to ARGB32 values */
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
unsigned int* dst = (unsigned int*)dstLine;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++ )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned int pix = srcLine[x];
|
|
Packit |
b749da |
|
|
Packit |
b749da |
pix |= (pix << 8);
|
|
Packit |
b749da |
pix |= (pix << 16);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
dst[x] = pix;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else /* copy gray into gray */
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
memcpy( dstLine, srcLine, width );
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
case FT_PIXEL_MODE_LCD:
|
|
Packit |
b749da |
if ( !bgr )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/* convert horizontal RGB into ARGB32 */
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
unsigned char* src = srcLine;
|
|
Packit |
b749da |
unsigned int* dst = (unsigned int*)dstLine;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++, src += 3 )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned int pix;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
pix = ((unsigned int)src[0] << 16) |
|
|
Packit |
b749da |
((unsigned int)src[1] << 8) |
|
|
Packit |
b749da |
((unsigned int)src[2] ) |
|
|
Packit |
b749da |
((unsigned int)src[1] << 24) ;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
dst[x] = pix;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/* convert horizontal BGR into ARGB32 */
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
unsigned char* src = srcLine;
|
|
Packit |
b749da |
unsigned int* dst = (unsigned int*)dstLine;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++, src += 3 )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned int pix;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
pix = ((unsigned int)src[2] << 16) |
|
|
Packit |
b749da |
((unsigned int)src[1] << 8) |
|
|
Packit |
b749da |
((unsigned int)src[0] ) |
|
|
Packit |
b749da |
((unsigned int)src[1] << 24) ;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
dst[x] = pix;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
default: /* FT_PIXEL_MODE_LCD_V */
|
|
Packit |
b749da |
/* convert vertical RGB into ARGB32 */
|
|
Packit |
b749da |
if ( !bgr )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
unsigned char* src = srcLine;
|
|
Packit |
b749da |
unsigned int* dst = (unsigned int*)dstLine;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++, src += 1 )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned int pix;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
pix = ((unsigned int)src[0] << 16) |
|
|
Packit |
b749da |
((unsigned int)src[src_pitch] << 8) |
|
|
Packit |
b749da |
((unsigned int)src[src_pitch*2] ) |
|
|
Packit |
b749da |
((unsigned int)src[src_pitch] << 24) ;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
dst[x] = pix;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x;
|
|
Packit |
b749da |
unsigned char* src = srcLine;
|
|
Packit |
b749da |
unsigned int* dst = (unsigned int*)dstLine;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for ( x = 0; x < width; x++, src += 1 )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned int pix;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
pix = ((unsigned int)src[src_pitch*2] << 16) |
|
|
Packit |
b749da |
((unsigned int)src[src_pitch] << 8) |
|
|
Packit |
b749da |
((unsigned int)src[0] ) |
|
|
Packit |
b749da |
((unsigned int)src[src_pitch] << 24) ;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
dst[x] = pix;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_X_EXPORT void
|
|
Packit |
b749da |
XftFontLoadGlyphs (Display *dpy,
|
|
Packit |
b749da |
XftFont *pub,
|
|
Packit |
b749da |
FcBool need_bitmaps,
|
|
Packit |
b749da |
_Xconst FT_UInt *glyphs,
|
|
Packit |
b749da |
int nglyph)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True);
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) pub;
|
|
Packit |
b749da |
FT_Error error;
|
|
Packit |
b749da |
FT_UInt glyphindex;
|
|
Packit |
b749da |
FT_GlyphSlot glyphslot;
|
|
Packit |
b749da |
XftGlyph *xftg;
|
|
Packit |
b749da |
Glyph glyph;
|
|
Packit |
b749da |
unsigned char bufLocal[4096];
|
|
Packit |
b749da |
unsigned char *bufBitmap = bufLocal;
|
|
Packit |
b749da |
int bufSize = sizeof (bufLocal);
|
|
Packit |
b749da |
int size;
|
|
Packit |
b749da |
int width;
|
|
Packit |
b749da |
int height;
|
|
Packit |
b749da |
int left, right, top, bottom;
|
|
Packit |
b749da |
FT_Bitmap* ftbit;
|
|
Packit |
b749da |
FT_Bitmap local;
|
|
Packit |
b749da |
FT_Vector vector;
|
|
Packit |
b749da |
FT_Face face;
|
|
Packit |
b749da |
FT_Render_Mode mode = FT_RENDER_MODE_MONO;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (!info)
|
|
Packit |
b749da |
return;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
face = XftLockFace (&font->public);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (!face)
|
|
Packit |
b749da |
return;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (font->info.antialias)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
switch (font->info.rgba) {
|
|
Packit |
b749da |
case FC_RGBA_RGB:
|
|
Packit |
b749da |
case FC_RGBA_BGR:
|
|
Packit |
b749da |
mode = FT_RENDER_MODE_LCD;
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
case FC_RGBA_VRGB:
|
|
Packit |
b749da |
case FC_RGBA_VBGR:
|
|
Packit |
b749da |
mode = FT_RENDER_MODE_LCD_V;
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
default:
|
|
Packit |
b749da |
mode = FT_RENDER_MODE_NORMAL;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
while (nglyph--)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
glyphindex = *glyphs++;
|
|
Packit |
b749da |
xftg = font->glyphs[glyphindex];
|
|
Packit |
b749da |
if (!xftg)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHE)
|
|
Packit |
b749da |
_XftFontValidateMemory (dpy, pub);
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Check to see if this glyph has just been loaded,
|
|
Packit |
b749da |
* this happens when drawing the same glyph twice
|
|
Packit |
b749da |
* in a single string
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if (xftg->glyph_memory)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
FT_Library_SetLcdFilter( _XftFTlibrary, font->info.lcd_filter);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
error = FT_Load_Glyph (face, glyphindex, font->info.load_flags);
|
|
Packit |
b749da |
if (error)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* If anti-aliasing or transforming glyphs and
|
|
Packit |
b749da |
* no outline version exists, fallback to the
|
|
Packit |
b749da |
* bitmap and let things look bad instead of
|
|
Packit |
b749da |
* missing the glyph
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if (font->info.load_flags & FT_LOAD_NO_BITMAP)
|
|
Packit |
b749da |
error = FT_Load_Glyph (face, glyphindex,
|
|
Packit |
b749da |
font->info.load_flags & ~FT_LOAD_NO_BITMAP);
|
|
Packit |
b749da |
if (error)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
#define FLOOR(x) ((x) & -64)
|
|
Packit |
b749da |
#define CEIL(x) (((x)+63) & -64)
|
|
Packit |
b749da |
#define TRUNC(x) ((x) >> 6)
|
|
Packit |
b749da |
#define ROUND(x) (((x)+32) & -64)
|
|
Packit |
b749da |
|
|
Packit |
b749da |
glyphslot = face->glyph;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Embolden if required
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if (font->info.embolden) FT_GlyphSlot_Embolden(glyphslot);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Compute glyph metrics from FreeType information
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* calculate the true width by transforming all four corners.
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
int xc, yc;
|
|
Packit |
b749da |
left = right = top = bottom = 0;
|
|
Packit |
b749da |
for(xc = 0; xc <= 1; xc ++) {
|
|
Packit |
b749da |
for(yc = 0; yc <= 1; yc++) {
|
|
Packit |
b749da |
vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width;
|
|
Packit |
b749da |
vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height;
|
|
Packit |
b749da |
FT_Vector_Transform(&vector, &font->info.matrix);
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_GLYPH)
|
|
Packit |
b749da |
printf("Trans %d %d: %d %d\n", (int) xc, (int) yc,
|
|
Packit |
b749da |
(int) vector.x, (int) vector.y);
|
|
Packit |
b749da |
if(xc == 0 && yc == 0) {
|
|
Packit |
b749da |
left = right = vector.x;
|
|
Packit |
b749da |
top = bottom = vector.y;
|
|
Packit |
b749da |
} else {
|
|
Packit |
b749da |
if(left > vector.x) left = vector.x;
|
|
Packit |
b749da |
if(right < vector.x) right = vector.x;
|
|
Packit |
b749da |
if(bottom > vector.y) bottom = vector.y;
|
|
Packit |
b749da |
if(top < vector.y) top = vector.y;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
left = FLOOR(left);
|
|
Packit |
b749da |
right = CEIL(right);
|
|
Packit |
b749da |
bottom = FLOOR(bottom);
|
|
Packit |
b749da |
top = CEIL(top);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
} else {
|
|
Packit |
b749da |
left = FLOOR( glyphslot->metrics.horiBearingX );
|
|
Packit |
b749da |
right = CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width );
|
|
Packit |
b749da |
|
|
Packit |
b749da |
top = CEIL( glyphslot->metrics.horiBearingY );
|
|
Packit |
b749da |
bottom = FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height );
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
width = TRUNC(right - left);
|
|
Packit |
b749da |
height = TRUNC( top - bottom );
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Clip charcell glyphs to the bounding box
|
|
Packit |
b749da |
* XXX transformed?
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if (font->info.spacing >= FC_CHARCELL && !font->info.transform)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (TRUNC(bottom) > font->public.max_advance_width)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int adjust;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
adjust = bottom - (font->public.max_advance_width << 6);
|
|
Packit |
b749da |
if (adjust > top)
|
|
Packit |
b749da |
adjust = top;
|
|
Packit |
b749da |
top -= adjust;
|
|
Packit |
b749da |
bottom -= adjust;
|
|
Packit |
b749da |
height = font->public.max_advance_width;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (TRUNC(right) > font->public.max_advance_width)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int adjust;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
adjust = right - (font->public.max_advance_width << 6);
|
|
Packit |
b749da |
if (adjust > left)
|
|
Packit |
b749da |
adjust = left;
|
|
Packit |
b749da |
left -= adjust;
|
|
Packit |
b749da |
right -= adjust;
|
|
Packit |
b749da |
width = font->public.max_advance_width;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
error = FT_Render_Glyph( face->glyph, mode );
|
|
Packit |
b749da |
if (error)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (font->info.spacing >= FC_MONO)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->info.transform)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
vector.x = 0;
|
|
Packit |
b749da |
vector.y = -face->size->metrics.max_advance;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
vector.x = face->size->metrics.max_advance;
|
|
Packit |
b749da |
vector.y = 0;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
FT_Vector_Transform (&vector, &font->info.matrix);
|
|
Packit |
b749da |
xftg->metrics.xOff = vector.x >> 6;
|
|
Packit |
b749da |
xftg->metrics.yOff = -(vector.y >> 6);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg->metrics.xOff = 0;
|
|
Packit |
b749da |
xftg->metrics.yOff = -font->public.max_advance_width;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg->metrics.xOff = font->public.max_advance_width;
|
|
Packit |
b749da |
xftg->metrics.yOff = 0;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg->metrics.xOff = TRUNC(ROUND(glyphslot->advance.x));
|
|
Packit |
b749da |
xftg->metrics.yOff = -TRUNC(ROUND(glyphslot->advance.y));
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
// compute the size of the final bitmap
|
|
Packit |
b749da |
ftbit = &glyphslot->bitmap;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
width = ftbit->width;
|
|
Packit |
b749da |
height = ftbit->rows;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_GLYPH)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
printf ("glyph %d:\n", (int) glyphindex);
|
|
Packit |
b749da |
printf (" xywh (%d %d %d %d), trans (%d %d %d %d) wh (%d %d)\n",
|
|
Packit |
b749da |
(int) glyphslot->metrics.horiBearingX,
|
|
Packit |
b749da |
(int) glyphslot->metrics.horiBearingY,
|
|
Packit |
b749da |
(int) glyphslot->metrics.width,
|
|
Packit |
b749da |
(int) glyphslot->metrics.height,
|
|
Packit |
b749da |
left, right, top, bottom,
|
|
Packit |
b749da |
width, height);
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_GLYPHV)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int x, y;
|
|
Packit |
b749da |
unsigned char *line;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
line = ftbit->buffer;
|
|
Packit |
b749da |
if (ftbit->pitch < 0)
|
|
Packit |
b749da |
line -= ftbit->pitch*(height-1);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
for (y = 0; y < height; y++)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->info.antialias)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
static const char den[] = { " .:;=+*#" };
|
|
Packit |
b749da |
for (x = 0; x < width; x++)
|
|
Packit |
b749da |
printf ("%c", den[line[x] >> 5]);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
for (x = 0; x < width * 8; x++)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
printf ("|\n");
|
|
Packit |
b749da |
line += ftbit->pitch;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
printf ("\n");
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
|
|
Packit |
b749da |
if ( size < 0 )
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
xftg->metrics.width = local.width;
|
|
Packit |
b749da |
xftg->metrics.height = local.rows;
|
|
Packit |
b749da |
xftg->metrics.x = - glyphslot->bitmap_left;
|
|
Packit |
b749da |
xftg->metrics.y = glyphslot->bitmap_top;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* If the glyph is relatively large (> 1% of server memory),
|
|
Packit |
b749da |
* don't send it until necessary.
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if (!need_bitmaps && size > info->max_glyph_memory / 100)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Make sure there is enough buffer space for the glyph.
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
if (size > bufSize)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (bufBitmap != bufLocal)
|
|
Packit |
b749da |
free (bufBitmap);
|
|
Packit |
b749da |
bufBitmap = (unsigned char *) malloc (size);
|
|
Packit |
b749da |
if (!bufBitmap)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
bufSize = size;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
memset (bufBitmap, 0, size);
|
|
Packit |
b749da |
|
|
Packit |
b749da |
local.buffer = bufBitmap;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_fill_xrender_bitmap( &local, glyphslot, mode,
|
|
Packit |
b749da |
(font->info.rgba == FC_RGBA_BGR ||
|
|
Packit |
b749da |
font->info.rgba == FC_RGBA_VBGR ) );
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Copy or convert into local buffer.
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Use the glyph index as the wire encoding; it
|
|
Packit |
b749da |
* might be more efficient for some locales to map
|
|
Packit |
b749da |
* these by first usage to smaller values, but that
|
|
Packit |
b749da |
* would require persistently storing the map when
|
|
Packit |
b749da |
* glyphs were freed.
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
glyph = (Glyph) glyphindex;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
xftg->glyph_memory = size + sizeof (XftGlyph);
|
|
Packit |
b749da |
if (font->format)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (!font->glyphset)
|
|
Packit |
b749da |
font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
|
|
Packit |
b749da |
if ( mode == FT_RENDER_MODE_MONO )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/* swap bits in each byte */
|
|
Packit |
b749da |
if (BitmapBitOrder (dpy) != MSBFirst)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
unsigned char *line = (unsigned char*)bufBitmap;
|
|
Packit |
b749da |
int i = size;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
while (i--)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
int c = *line;
|
|
Packit |
b749da |
c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
|
|
Packit |
b749da |
c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
|
|
Packit |
b749da |
c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
|
|
Packit |
b749da |
*line++ = c;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else if ( mode != FT_RENDER_MODE_NORMAL )
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
/* invert ARGB <=> BGRA */
|
|
Packit |
b749da |
if (ImageByteOrder (dpy) != XftNativeByteOrder ())
|
|
Packit |
b749da |
XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
XRenderAddGlyphs (dpy, font->glyphset, &glyph,
|
|
Packit |
b749da |
&xftg->metrics, 1,
|
|
Packit |
b749da |
(char *) bufBitmap, size);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (size)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg->bitmap = malloc (size);
|
|
Packit |
b749da |
if (xftg->bitmap)
|
|
Packit |
b749da |
memcpy (xftg->bitmap, bufBitmap, size);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
xftg->bitmap = NULL;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
font->glyph_memory += xftg->glyph_memory;
|
|
Packit |
b749da |
info->glyph_memory += xftg->glyph_memory;
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHE)
|
|
Packit |
b749da |
_XftFontValidateMemory (dpy, pub);
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHEV)
|
|
Packit |
b749da |
printf ("Caching glyph 0x%x size %ld\n", glyphindex,
|
|
Packit |
b749da |
xftg->glyph_memory);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
if (bufBitmap != bufLocal)
|
|
Packit |
b749da |
free (bufBitmap);
|
|
Packit |
b749da |
XftUnlockFace (&font->public);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_X_EXPORT void
|
|
Packit |
b749da |
XftFontUnloadGlyphs (Display *dpy,
|
|
Packit |
b749da |
XftFont *pub,
|
|
Packit |
b749da |
_Xconst FT_UInt *glyphs,
|
|
Packit |
b749da |
int nglyph)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False);
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) pub;
|
|
Packit |
b749da |
XftGlyph *xftg;
|
|
Packit |
b749da |
FT_UInt glyphindex;
|
|
Packit |
b749da |
Glyph glyphBuf[1024];
|
|
Packit |
b749da |
int nused;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
nused = 0;
|
|
Packit |
b749da |
while (nglyph--)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
glyphindex = *glyphs++;
|
|
Packit |
b749da |
xftg = font->glyphs[glyphindex];
|
|
Packit |
b749da |
if (!xftg)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
if (xftg->glyph_memory)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->format)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->glyphset)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
glyphBuf[nused++] = (Glyph) glyphindex;
|
|
Packit |
b749da |
if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
|
|
Packit |
b749da |
nused = 0;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (xftg->bitmap)
|
|
Packit |
b749da |
free (xftg->bitmap);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
font->glyph_memory -= xftg->glyph_memory;
|
|
Packit |
b749da |
if (info)
|
|
Packit |
b749da |
info->glyph_memory -= xftg->glyph_memory;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
free (xftg);
|
|
Packit |
b749da |
XftMemFree (XFT_MEM_GLYPH, sizeof (XftGlyph));
|
|
Packit |
b749da |
font->glyphs[glyphindex] = NULL;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
if (font->glyphset && nused)
|
|
Packit |
b749da |
XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_X_EXPORT FcBool
|
|
Packit |
b749da |
XftFontCheckGlyph (Display *dpy,
|
|
Packit |
b749da |
XftFont *pub,
|
|
Packit |
b749da |
FcBool need_bitmaps,
|
|
Packit |
b749da |
FT_UInt glyph,
|
|
Packit |
b749da |
FT_UInt *missing,
|
|
Packit |
b749da |
int *nmissing)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) pub;
|
|
Packit |
b749da |
XftGlyph *xftg;
|
|
Packit |
b749da |
int n;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (glyph >= font->num_glyphs)
|
|
Packit |
b749da |
return FcFalse;
|
|
Packit |
b749da |
xftg = font->glyphs[glyph];
|
|
Packit |
b749da |
if (!xftg || (need_bitmaps && !xftg->glyph_memory))
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (!xftg)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg = (XftGlyph *) malloc (sizeof (XftGlyph));
|
|
Packit |
b749da |
if (!xftg)
|
|
Packit |
b749da |
return FcFalse;
|
|
Packit |
b749da |
XftMemAlloc (XFT_MEM_GLYPH, sizeof (XftGlyph));
|
|
Packit |
b749da |
xftg->bitmap = NULL;
|
|
Packit |
b749da |
xftg->glyph_memory = 0;
|
|
Packit |
b749da |
font->glyphs[glyph] = xftg;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
n = *nmissing;
|
|
Packit |
b749da |
missing[n++] = glyph;
|
|
Packit |
b749da |
if (n == XFT_NMISSING)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n);
|
|
Packit |
b749da |
n = 0;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
*nmissing = n;
|
|
Packit |
b749da |
return FcTrue;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
return FcFalse;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_X_EXPORT FcBool
|
|
Packit |
b749da |
XftCharExists (Display *dpy,
|
|
Packit |
b749da |
XftFont *pub,
|
|
Packit |
b749da |
FcChar32 ucs4)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (pub->charset)
|
|
Packit |
b749da |
return FcCharSetHasChar (pub->charset, ucs4);
|
|
Packit |
b749da |
return FcFalse;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
#define Missing ((FT_UInt) ~0)
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_X_EXPORT FT_UInt
|
|
Packit |
b749da |
XftCharIndex (Display *dpy,
|
|
Packit |
b749da |
XftFont *pub,
|
|
Packit |
b749da |
FcChar32 ucs4)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) pub;
|
|
Packit |
b749da |
FcChar32 ent, offset;
|
|
Packit |
b749da |
FT_Face face;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (!font->hash_value)
|
|
Packit |
b749da |
return 0;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
ent = ucs4 % font->hash_value;
|
|
Packit |
b749da |
offset = 0;
|
|
Packit |
b749da |
while (font->hash_table[ent].ucs4 != ucs4)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->hash_table[ent].ucs4 == (FcChar32) ~0)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (!XftCharExists (dpy, pub, ucs4))
|
|
Packit |
b749da |
return 0;
|
|
Packit |
b749da |
face = XftLockFace (pub);
|
|
Packit |
b749da |
if (!face)
|
|
Packit |
b749da |
return 0;
|
|
Packit |
b749da |
font->hash_table[ent].ucs4 = ucs4;
|
|
Packit |
b749da |
font->hash_table[ent].glyph = FcFreeTypeCharIndex (face, ucs4);
|
|
Packit |
b749da |
XftUnlockFace (pub);
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
if (!offset)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
offset = ucs4 % font->rehash_value;
|
|
Packit |
b749da |
if (!offset)
|
|
Packit |
b749da |
offset = 1;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
ent = ent + offset;
|
|
Packit |
b749da |
if (ent >= font->hash_value)
|
|
Packit |
b749da |
ent -= font->hash_value;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
return font->hash_table[ent].glyph;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
/*
|
|
Packit |
b749da |
* Pick a random glyph from the font and remove it from the cache
|
|
Packit |
b749da |
*/
|
|
Packit |
b749da |
_X_HIDDEN void
|
|
Packit |
b749da |
_XftFontUncacheGlyph (Display *dpy, XftFont *pub)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) pub;
|
|
Packit |
b749da |
unsigned long glyph_memory;
|
|
Packit |
b749da |
FT_UInt glyphindex;
|
|
Packit |
b749da |
XftGlyph *xftg;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (!font->glyph_memory)
|
|
Packit |
b749da |
return;
|
|
Packit |
b749da |
if (font->use_free_glyphs)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
glyph_memory = rand() % font->glyph_memory;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
else
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->glyphset)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XRenderFreeGlyphSet (dpy, font->glyphset);
|
|
Packit |
b749da |
font->glyphset = 0;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
glyph_memory = 0;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHE)
|
|
Packit |
b749da |
_XftFontValidateMemory (dpy, pub);
|
|
Packit |
b749da |
for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
xftg = font->glyphs[glyphindex];
|
|
Packit |
b749da |
if (xftg)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (xftg->glyph_memory > glyph_memory)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHEV)
|
|
Packit |
b749da |
printf ("Uncaching glyph 0x%x size %ld\n",
|
|
Packit |
b749da |
glyphindex, xftg->glyph_memory);
|
|
Packit |
b749da |
XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
|
|
Packit |
b749da |
if (!font->use_free_glyphs)
|
|
Packit |
b749da |
continue;
|
|
Packit |
b749da |
break;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
glyph_memory -= xftg->glyph_memory;
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHE)
|
|
Packit |
b749da |
_XftFontValidateMemory (dpy, pub);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
|
|
Packit |
b749da |
_X_HIDDEN void
|
|
Packit |
b749da |
_XftFontManageMemory (Display *dpy, XftFont *pub)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
XftFontInt *font = (XftFontInt *) pub;
|
|
Packit |
b749da |
|
|
Packit |
b749da |
if (font->max_glyph_memory)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (XftDebug() & XFT_DBG_CACHE)
|
|
Packit |
b749da |
{
|
|
Packit |
b749da |
if (font->glyph_memory > font->max_glyph_memory)
|
|
Packit |
b749da |
printf ("Reduce memory for font 0x%lx from %ld to %ld\n",
|
|
Packit |
b749da |
font->glyphset ? font->glyphset : (unsigned long) font,
|
|
Packit |
b749da |
font->glyph_memory, font->max_glyph_memory);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
while (font->glyph_memory > font->max_glyph_memory)
|
|
Packit |
b749da |
_XftFontUncacheGlyph (dpy, pub);
|
|
Packit |
b749da |
}
|
|
Packit |
b749da |
_XftDisplayManageMemory (dpy);
|
|
Packit |
b749da |
}
|