Module Name: xsrc
Committed By: mrg
Date: Fri Sep 9 23:18:56 UTC 2022
Modified Files:
xsrc/external/mit/libXft/dist/src: xftdpy.c xftglyphs.c
Log Message:
merge libXft 2.3.5.
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 xsrc/external/mit/libXft/dist/src/xftdpy.c
cvs rdiff -u -r1.4 -r1.5 xsrc/external/mit/libXft/dist/src/xftglyphs.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: xsrc/external/mit/libXft/dist/src/xftdpy.c
diff -u xsrc/external/mit/libXft/dist/src/xftdpy.c:1.5 xsrc/external/mit/libXft/dist/src/xftdpy.c:1.6
--- xsrc/external/mit/libXft/dist/src/xftdpy.c:1.5 Mon Aug 23 21:05:09 2021
+++ xsrc/external/mit/libXft/dist/src/xftdpy.c Fri Sep 9 23:18:56 2022
@@ -22,10 +22,12 @@
#include "xftint.h"
+#define BtoS(b) ((b) ? "true" : "false")
+
_X_HIDDEN XftDisplayInfo *_XftDisplayInfo;
static int
-_XftCloseDisplay (Display *dpy, XExtCodes *codes)
+_XftCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED)
{
XftDisplayInfo *info, **prev;
@@ -51,7 +53,8 @@ _XftCloseDisplay (Display *dpy, XExtCode
for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next)
if (info->display == dpy)
break;
- *prev = info->next;
+ if (info != NULL)
+ *prev = info->next;
free (info);
return 0;
@@ -85,7 +88,7 @@ _XftDisplayInfoGet (Display *dpy, FcBool
if (!createIfNecessary)
return NULL;
- info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo));
+ info = malloc (sizeof (XftDisplayInfo));
if (!info)
goto bail0;
info->codes = XAddExtension (dpy);
@@ -169,7 +172,7 @@ _XftDisplayInfoGet (Display *dpy, FcBool
XFT_MAX_GLYPH_MEMORY, 0,
XFT_DPY_MAX_GLYPH_MEMORY);
if (XftDebug () & XFT_DBG_CACHE)
- printf ("global max cache memory %ld\n", info->max_glyph_memory);
+ printf ("global max cache memory %lu\n", info->max_glyph_memory);
info->num_unref_fonts = 0;
@@ -177,7 +180,14 @@ _XftDisplayInfoGet (Display *dpy, FcBool
XFT_MAX_UNREF_FONTS, 0,
XFT_DPY_MAX_UNREF_FONTS);
if (XftDebug() & XFT_DBG_CACHE)
- printf ("global max unref fonts %d\n", info->max_unref_fonts);
+ printf ("global max unref fonts %d\n", info->max_unref_fonts);
+
+ info->track_mem_usage = FcFalse;
+ info->track_mem_usage = XftDefaultGetBool (dpy,
+ XFT_TRACK_MEM_USAGE, 0,
+ FcFalse);
+ if (XftDebug() & XFT_DBG_CACHE)
+ printf ("global track mem usage %s\n", BtoS(info->track_mem_usage));
memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH);
return info;
@@ -210,7 +220,7 @@ _XftDisplayValidateMemory (XftDisplayInf
glyph_memory += font->glyph_memory;
}
if (glyph_memory != info->glyph_memory)
- printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n",
+ printf ("Display glyph cache incorrect has %lu bytes, should have %lu\n",
info->glyph_memory, glyph_memory);
}
@@ -227,7 +237,7 @@ _XftDisplayManageMemory (Display *dpy)
if (XftDebug () & XFT_DBG_CACHE)
{
if (info->glyph_memory > info->max_glyph_memory)
- printf ("Reduce global memory from %ld to %ld\n",
+ printf ("Reduce global memory from %lu to %lu\n",
info->glyph_memory, info->max_glyph_memory);
_XftDisplayValidateMemory (info);
}
@@ -272,16 +282,29 @@ XftDefaultSet (Display *dpy, FcPattern *
if (info->defaults)
FcPatternDestroy (info->defaults);
info->defaults = defaults;
+
if (!info->max_glyph_memory)
info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY;
info->max_glyph_memory = (unsigned long)XftDefaultGetInteger (dpy,
XFT_MAX_GLYPH_MEMORY, 0,
(int)info->max_glyph_memory);
+ if (XftDebug () & XFT_DBG_CACHE)
+ printf ("update max cache memory %lu\n", info->max_glyph_memory);
+
if (!info->max_unref_fonts)
info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS;
info->max_unref_fonts = XftDefaultGetInteger (dpy,
XFT_MAX_UNREF_FONTS, 0,
info->max_unref_fonts);
+ if (XftDebug() & XFT_DBG_CACHE)
+ printf ("update max unref fonts %d\n", info->max_unref_fonts);
+
+ info->track_mem_usage = XftDefaultGetBool (dpy,
+ XFT_TRACK_MEM_USAGE, 0,
+ info->track_mem_usage);
+ if (XftDebug() & XFT_DBG_CACHE)
+ printf ("update track mem usage %s\n", BtoS(info->track_mem_usage));
+
return True;
}
Index: xsrc/external/mit/libXft/dist/src/xftglyphs.c
diff -u xsrc/external/mit/libXft/dist/src/xftglyphs.c:1.4 xsrc/external/mit/libXft/dist/src/xftglyphs.c:1.5
--- xsrc/external/mit/libXft/dist/src/xftglyphs.c:1.4 Mon Aug 23 21:05:09 2021
+++ xsrc/external/mit/libXft/dist/src/xftglyphs.c Fri Sep 9 23:18:56 2022
@@ -1,23 +1,24 @@
/*
+ * Copyright © 2022 Thomas E. Dickey
* Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the above copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The above copyright holders make no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "xftint.h"
@@ -26,12 +27,54 @@
#include FT_SYNTHESIS_H
+#include FT_GLYPH_H
+
+typedef double m3x3[3][3];
+
+static void
+m3x3_uniform(m3x3 m)
+{
+ m[0][0] = m[1][1] = m[2][2] = 1.0;
+ m[0][1] = m[1][0] = m[0][2] = m[1][2] = m[2][0] = m[2][1] = 0;
+}
+
+static void
+m3x3_transform(FT_Vector *v, m3x3 m)
+{
+ double x, y;
+
+ x = (double)v->x;
+ y = (double)v->y;
+ v->x = (FT_Pos)(x * m[0][0] + y * m[0][1] + m[0][2] + 0.5);
+ v->y = (FT_Pos)(x * m[1][0] + y * m[1][1] + m[1][2] + 0.5);
+}
+
+static void
+m3x3_invert(m3x3 m, m3x3 mi)
+{
+ double det;
+
+ det = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
+ det -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]);
+ det += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+ det = 1.0 / det;
+ mi[0][0] = det * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
+ mi[1][0] = det * (m[1][2] * m[2][0] - m[1][0] * m[2][2]);
+ mi[2][0] = det * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+ mi[0][1] = det * (m[0][2] * m[2][1] - m[0][1] * m[2][2]);
+ mi[1][1] = det * (m[0][0] * m[2][2] - m[0][2] * m[2][0]);
+ mi[2][1] = det * (m[0][1] * m[2][0] - m[0][0] * m[2][1]);
+ mi[0][2] = det * (m[0][1] * m[1][2] - m[0][2] * m[1][1]);
+ mi[1][2] = det * (m[0][2] * m[1][0] - m[0][0] * m[1][2]);
+ mi[2][2] = det * (m[0][0] * m[1][1] - m[0][1] * m[1][0]);
+}
+
/*
* Validate the memory info for a font
*/
static void
-_XftFontValidateMemory (Display *dpy, XftFont *public)
+_XftFontValidateMemory (Display *dpy _X_UNUSED, XftFont *public)
{
XftFontInt *font = (XftFontInt *) public;
unsigned long glyph_memory;
@@ -48,10 +91,72 @@ _XftFontValidateMemory (Display *dpy, Xf
}
}
if (glyph_memory != font->glyph_memory)
- printf ("Font glyph cache incorrect has %ld bytes, should have %ld\n",
+ printf ("Font glyph cache incorrect has %lu bytes, should have %lu\n",
font->glyph_memory, glyph_memory);
}
+/*
+ * Validate the glyph usage-links for a font.
+ */
+static void
+_XftValidateGlyphUsage(XftFontInt *font)
+{
+ if (font->newest != FT_UINT_MAX) {
+ FT_UInt forward;
+ FT_UInt reverse;
+ FT_UInt next;
+ XftGlyphUsage *x1st = (XftGlyphUsage *) font->glyphs[font->newest];
+ XftGlyphUsage *xuse = x1st;
+ for (forward = 1,
+ next = x1st->newer;
+ xuse != NULL &&
+ next != font->newest;
+ next = xuse->newer) {
+ if (next >= font->num_glyphs) {
+ printf("Xft: out of range; %d\n", next);
+ break;
+ }
+ if (++forward > font->total_inuse) {
+ printf("Xft: too many in-use glyphs (%d vs %d)\n",
+ forward, font->total_inuse);
+ if (forward > font->total_inuse + 10)
+ break;
+ }
+ xuse = (XftGlyphUsage *) font->glyphs[next];
+ }
+ if (forward < font->total_inuse) {
+ printf("Xft: too few in-use glyphs (%u vs %d)\n",
+ forward, font->total_inuse);
+ }
+ for (reverse = 1,
+ next = x1st->older;
+ xuse != NULL &&
+ next != font->newest;
+ next = xuse->older) {
+ if (next >= font->num_glyphs) {
+ printf("Xft out of range; %d\n", next);
+ break;
+ }
+ if (++reverse > font->total_inuse) {
+ printf("Xft: too many in-use glyphs (%d vs %d)\n",
+ reverse, font->total_inuse);
+ if (reverse > font->total_inuse + 10)
+ break;
+ }
+ xuse = (XftGlyphUsage *) font->glyphs[next];
+ }
+ if (reverse < font->total_inuse) {
+ printf("Xft: too few in-use glyphs (%u vs %d)\n",
+ reverse, font->total_inuse);
+ }
+ if (forward != reverse) {
+ printf("Xft: forward %d vs reverse %d\n",
+ forward, reverse);
+ exit(1);
+ }
+ }
+}
+
/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
* into a different format. For example, we want to convert a
* FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
@@ -78,7 +183,9 @@ _XftFontValidateMemory (Display *dpy, Xf
static int
_compute_xrender_bitmap_size( FT_Bitmap* target,
FT_GlyphSlot slot,
- FT_Render_Mode mode )
+ FT_Render_Mode mode,
+ FT_Matrix* matrix,
+ m3x3 m )
{
FT_Bitmap* ftbit;
int width, height, pitch;
@@ -91,6 +198,63 @@ _compute_xrender_bitmap_size( FT_Bitmap*
width = (int)ftbit->width;
height = (int)ftbit->rows;
+
+ if ( matrix && mode == FT_RENDER_MODE_NORMAL )
+ {
+ FT_Matrix mirror, inverse;
+ FT_Vector vector;
+ int xc, yc;
+ int left, right, top, bottom;
+
+ left = right = top = bottom = 0;
+ for (xc = 0; xc <= 1; xc++) {
+ for (yc = 0; yc <= 1; yc++) {
+ vector.x = xc * width;
+ vector.y = yc * height;
+ FT_Vector_Transform(&vector, matrix);
+ if (xc == 0 && yc == 0) {
+ left = right = (int)vector.x;
+ top = bottom = (int)vector.y;
+ } else {
+ if (left > vector.x) left = (int)vector.x;
+ if (right < vector.x) right = (int)vector.x;
+ if (bottom > vector.y) bottom = (int)vector.y;
+ if (top < vector.y) top = (int)vector.y;
+ }
+ }
+ }
+ width = (int)(right - left);
+ height = (int)(top - bottom);
+
+ mirror.xx = + 0x10000;
+ mirror.yy = - 0x10000;
+ mirror.xy = mirror.yx = 0;
+ inverse = *matrix;
+ FT_Matrix_Multiply(&mirror, &inverse);
+ FT_Matrix_Invert(&inverse);
+ FT_Matrix_Multiply(&mirror, &inverse);
+
+ vector.x = vector.y = 0;
+ FT_Vector_Transform(&vector, &inverse);
+ left = (int)vector.x;
+ bottom = (int)vector.y;
+ vector.x = width;
+ vector.y = height;
+ FT_Vector_Transform(&vector, &inverse);
+ right = (int)vector.x;
+ top = (int)vector.y;
+ left = (right - left) - (int)ftbit->width;
+ bottom = (top - bottom) - (int)ftbit->rows;
+
+ m[0][0] = (double)inverse.xx / 0x10000;
+ m[0][1] = (double)inverse.xy / 0x10000;
+ m[1][0] = (double)inverse.yx / 0x10000;
+ m[1][1] = (double)inverse.yy / 0x10000;
+ m[0][2] = (double)-left / 2;
+ m[1][2] = (double)-bottom / 2;
+ m[2][0] = m[2][1] = 0.0;
+ m[2][2] = 1.0;
+ }
pitch = (width+3) & ~3;
switch ( ftbit->pixel_mode )
@@ -112,6 +276,10 @@ _compute_xrender_bitmap_size( FT_Bitmap*
}
break;
+ case FT_PIXEL_MODE_BGRA:
+ pitch = width * 4;
+ break;
+
case FT_PIXEL_MODE_LCD:
if ( mode != FT_RENDER_MODE_LCD )
return -1;
@@ -143,6 +311,125 @@ _compute_xrender_bitmap_size( FT_Bitmap*
}
/* this functions converts the glyph bitmap found in a FT_GlyphSlot
+ * into a different format while scaling by applying the given matrix
+ * (see _compute_xrender_bitmap_size)
+ *
+ * you should call this function after _compute_xrender_bitmap_size
+ *
+ * target :: target bitmap descriptor. Note that its 'buffer' pointer
+ * must point to memory allocated by the caller
+ *
+ * source :: the source bitmap descriptor
+ *
+ * matrix :: the scaling matrix to apply
+ */
+static void
+_scaled_fill_xrender_bitmap( FT_Bitmap* target,
+ FT_Bitmap* source,
+ m3x3 m )
+{
+ unsigned char* src_buf = source->buffer;
+ unsigned char* dst_line = target->buffer;
+ int src_pitch = source->pitch;
+ int width = (int) target->width;
+ int height = (int) target->rows;
+ int pitch = target->pitch;
+ int i, x, y;
+ FT_Vector vector, vector0;
+ int sampling_width;
+ int sampling_height;
+ int sample_count;
+
+ if ( src_pitch < 0 )
+ src_buf -= ((unsigned) src_pitch * (source->rows - 1));
+
+ /* compute how many source pixels a target pixel spans */
+ vector.x = 1;
+ vector.y = 1;
+ m3x3_transform(&vector, m);
+ vector0.x = 0;
+ vector0.y = 0;
+ m3x3_transform(&vector0, m);
+ sampling_width = (int) ((vector.x - vector0.x) / 2);
+ sampling_height = (int) ((vector.y - vector0.y) / 2);
+ if (sampling_width < 0) sampling_width = -sampling_width;
+ if (sampling_height < 0) sampling_height = -sampling_height;
+ sample_count = (2 * sampling_width + 1) * (2 * sampling_height + 1);
+
+ for ( y = height; y > 0; y--, dst_line += pitch )
+ {
+ for ( x = 0; x < width; x++ )
+ {
+ unsigned char* src;
+
+ /* compute target pixel location in source space */
+ vector.x = x;
+ vector.y = height - y;
+ m3x3_transform(&vector, m);
+
+ if (source->pixel_mode == FT_PIXEL_MODE_BGRA)
+ {
+ if (vector.x < -sampling_width
+ || vector.x > (source->width + (unsigned) sampling_width))
+ continue;
+ if (vector.y < -sampling_height
+ || vector.y > (source->rows + (unsigned) sampling_height))
+ continue;
+ }
+ else
+ {
+ if (vector.x < 0 || vector.x >= source->width)
+ continue;
+ if (vector.y < 0 || vector.y >= source->rows)
+ continue;
+ }
+
+ switch ( source->pixel_mode )
+ {
+ case FT_PIXEL_MODE_MONO: /* convert mono to 8-bit gray, scale using nearest pixel */
+ src = src_buf + (vector.y * src_pitch);
+ if ( src[(vector.x >> 3)] & (0x80 >> (vector.x & 7)) )
+ dst_line[x] = 0xff;
+ break;
+
+ case FT_PIXEL_MODE_GRAY: /* scale using nearest pixel */
+ src = src_buf + (vector.y * src_pitch);
+ dst_line[x] = src[vector.x];
+ break;
+
+ case FT_PIXEL_MODE_BGRA: /* scale by averaging all relevant source pixels, keep BGRA format */
+ {
+ int sample_x, sample_y;
+ int bgra[4] = { 0, 0, 0, 0 };
+
+ for (sample_y = - sampling_height; sample_y < sampling_height + 1; ++sample_y)
+ {
+ int src_y = (int) (vector.y + sample_y);
+
+ if (src_y < 0 || (FT_Pos) src_y >= source->rows)
+ continue;
+ src = src_buf + (src_y * src_pitch);
+ for (sample_x = - sampling_width; sample_x < sampling_width + 1; ++sample_x)
+ {
+ int src_x = (int) (vector.x + sample_x);
+
+ if (src_x < 0 || (FT_Pos) src_x >= source->width)
+ continue;
+ for (i = 0; i < 4; ++i)
+ bgra[i] += src[src_x * 4 + i];
+ }
+ }
+
+ for (i = 0; i < 4; ++i)
+ dst_line[4 * x + i] = (unsigned char) (bgra[i] / sample_count);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* this functions converts the glyph bitmap found in a FT_GlyphSlot
* into a different format (see _compute_xrender_bitmap_size)
*
* you should call this function after _compute_xrender_bitmap_size
@@ -166,15 +453,15 @@ _fill_xrender_bitmap( FT_Bitmap* target,
{
unsigned char* srcLine = ftbit->buffer;
- unsigned char* dstLine = target->buffer;
- int src_pitch = ftbit->pitch;
- int width = (int)target->width;
- int height = (int)target->rows;
- int pitch = target->pitch;
- int subpixel;
- int h;
+ unsigned char* dstLine = target->buffer;
+ int src_pitch = ftbit->pitch;
+ int width = (int)target->width;
+ int height = (int)target->rows;
+ int pitch = target->pitch;
+ int subpixel;
+ int h;
- subpixel = ( mode == FT_RENDER_MODE_LCD ||
+ subpixel = ( mode == FT_RENDER_MODE_LCD ||
mode == FT_RENDER_MODE_LCD_V );
if ( src_pitch < 0 )
@@ -244,6 +531,11 @@ _fill_xrender_bitmap( FT_Bitmap* target,
}
break;
+ case FT_PIXEL_MODE_BGRA: /* Preserve BGRA format */
+ for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
+ memcpy( dstLine, srcLine, (size_t) width * 4 );
+ break;
+
case FT_PIXEL_MODE_LCD:
if ( !bgr )
{
@@ -363,8 +655,11 @@ XftFontLoadGlyphs (Display *dpy,
FT_Bitmap* ftbit;
FT_Bitmap local;
FT_Vector vector;
+ m3x3 m;
FT_Face face;
FT_Render_Mode mode = FT_RENDER_MODE_MONO;
+ FcBool transform;
+ FcBool glyph_transform;
if (!info)
return;
@@ -374,6 +669,8 @@ XftFontLoadGlyphs (Display *dpy,
if (!face)
return;
+ if (font->info.color)
+ mode = FT_RENDER_MODE_NORMAL;
if (font->info.antialias)
{
switch (font->info.rgba) {
@@ -390,6 +687,8 @@ XftFontLoadGlyphs (Display *dpy,
}
}
+ transform = font->info.transform && mode != FT_RENDER_MODE_MONO;
+
while (nglyph--)
{
glyphindex = *glyphs++;
@@ -440,29 +739,29 @@ XftFontLoadGlyphs (Display *dpy,
/*
* Compute glyph metrics from FreeType information
*/
- if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
+ if (transform)
{
/*
* calculate the true width by transforming all four corners.
*/
int xc, yc;
left = right = top = bottom = 0;
- for(xc = 0; xc <= 1; xc ++) {
- for(yc = 0; yc <= 1; yc++) {
+ for (xc = 0; xc <= 1; xc++) {
+ for (yc = 0; yc <= 1; yc++) {
vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width;
vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height;
FT_Vector_Transform(&vector, &font->info.matrix);
if (XftDebug() & XFT_DBG_GLYPH)
printf("Trans %d %d: %d %d\n", (int) xc, (int) yc,
(int) vector.x, (int) vector.y);
- if(xc == 0 && yc == 0) {
+ if (xc == 0 && yc == 0) {
left = right = (int)vector.x;
top = bottom = (int)vector.y;
} else {
- if(left > vector.x) left = (int)vector.x;
- if(right < vector.x) right = (int)vector.x;
- if(bottom > vector.y) bottom = (int)vector.y;
- if(top < vector.y) top = (int)vector.y;
+ if (left > vector.x) left = (int)vector.x;
+ if (right < vector.x) right = (int)vector.x;
+ if (bottom > vector.y) bottom = (int)vector.y;
+ if (top < vector.y) top = (int)vector.y;
}
}
@@ -470,7 +769,7 @@ XftFontLoadGlyphs (Display *dpy,
left = (int)FLOOR(left);
right = (int)CEIL(right);
bottom = (int)FLOOR(bottom);
- top = CEIL(top);
+ top = (int)CEIL(top);
} else {
left = (int)FLOOR( glyphslot->metrics.horiBearingX );
@@ -480,14 +779,11 @@ XftFontLoadGlyphs (Display *dpy,
bottom = (int)FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height );
}
- width = TRUNC(right - left);
- height = TRUNC( top - bottom );
-
/*
* Clip charcell glyphs to the bounding box
* XXX transformed?
*/
- if (font->info.spacing >= FC_CHARCELL && !font->info.transform)
+ if (font->info.spacing >= FC_CHARCELL && !transform)
{
if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
{
@@ -500,7 +796,6 @@ XftFontLoadGlyphs (Display *dpy,
adjust = top;
top -= adjust;
bottom -= adjust;
- height = font->public.max_advance_width;
}
}
else
@@ -514,23 +809,24 @@ XftFontLoadGlyphs (Display *dpy,
adjust = left;
left -= adjust;
right -= adjust;
- width = font->public.max_advance_width;
}
}
}
+ glyph_transform = transform;
if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
{
error = FT_Render_Glyph( face->glyph, mode );
if (error)
continue;
+ glyph_transform = False;
}
FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
if (font->info.spacing >= FC_MONO)
{
- if (font->info.transform)
+ if (transform)
{
if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
{
@@ -542,9 +838,9 @@ XftFontLoadGlyphs (Display *dpy,
vector.x = face->size->metrics.max_advance;
vector.y = 0;
}
- FT_Vector_Transform (&vector, &font->info.matrix);
- xftg->metrics.xOff = (short)(vector.x >> 6);
- xftg->metrics.yOff = (short)(-(vector.y >> 6));
+ FT_Vector_Transform(&vector, &font->info.matrix);
+ xftg->metrics.xOff = (short)(TRUNC(ROUND(vector.x)));
+ xftg->metrics.yOff = (short)(TRUNC(ROUND(vector.y)));
}
else
{
@@ -603,7 +899,7 @@ XftFontLoadGlyphs (Display *dpy,
{
for (x = 0; x < width * 8; x++)
{
- printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
+ printf ("%c", (line[x>>3] & (1 << (x & 7))) ? '#' : ' ');
}
}
printf ("|\n");
@@ -613,20 +909,35 @@ XftFontLoadGlyphs (Display *dpy,
}
}
- size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
+ m3x3_uniform(m);
+ size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL, m );
if ( size < 0 )
continue;
xftg->metrics.width = (unsigned short)local.width;
xftg->metrics.height = (unsigned short)local.rows;
- xftg->metrics.x = (short)(- glyphslot->bitmap_left);
- xftg->metrics.y = (short)( glyphslot->bitmap_top);
+ if (glyph_transform)
+ {
+ m3x3 mi;
+
+ m3x3_invert(m, mi);
+ vector.x = - glyphslot->bitmap_left;
+ vector.y = glyphslot->bitmap_top;
+ m3x3_transform(&vector, mi);
+ xftg->metrics.x = (short)vector.x;
+ xftg->metrics.y = (short)vector.y;
+ }
+ else
+ {
+ xftg->metrics.x = (short)(- glyphslot->bitmap_left);
+ xftg->metrics.y = (short)( glyphslot->bitmap_top);
+ }
/*
* If the glyph is relatively large (> 1% of server memory),
* don't send it until necessary.
*/
- if (!need_bitmaps && size > info->max_glyph_memory / 100)
+ if (!need_bitmaps && ((unsigned long) size > (info->max_glyph_memory / 100)))
continue;
/*
@@ -645,9 +956,12 @@ XftFontLoadGlyphs (Display *dpy,
local.buffer = bufBitmap;
- _fill_xrender_bitmap( &local, glyphslot, mode,
- (font->info.rgba == FC_RGBA_BGR ||
- font->info.rgba == FC_RGBA_VBGR ) );
+ if (mode == FT_RENDER_MODE_NORMAL && glyph_transform)
+ _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, m);
+ else
+ _fill_xrender_bitmap( &local, glyphslot, mode,
+ (font->info.rgba == FC_RGBA_BGR ||
+ font->info.rgba == FC_RGBA_VBGR) );
/*
* Copy or convert into local buffer.
@@ -662,7 +976,12 @@ XftFontLoadGlyphs (Display *dpy,
*/
glyph = (Glyph) glyphindex;
- xftg->glyph_memory = (size_t)size + sizeof (XftGlyph);
+ if (xftg->picture)
+ {
+ XRenderFreePicture(dpy, xftg->picture);
+ xftg->picture = 0;
+ }
+ xftg->glyph_memory = (size_t)size + font->sizeof_glyph;
if (font->format)
{
if (!font->glyphset)
@@ -685,15 +1004,43 @@ XftFontLoadGlyphs (Display *dpy,
}
}
}
- else if ( mode != FT_RENDER_MODE_NORMAL )
+ else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL)
{
/* invert ARGB <=> BGRA */
if (ImageByteOrder (dpy) != XftNativeByteOrder ())
XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
}
- XRenderAddGlyphs (dpy, font->glyphset, &glyph,
- &xftg->metrics, 1,
- (char *) bufBitmap, size);
+
+ if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
+ {
+ Pixmap pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), local.width, local.rows, 32);
+ GC gc = XCreateGC(dpy, pixmap, 0, NULL);
+ XImage image = {
+ (int) local.width, (int) local.rows, 0, ZPixmap, (char *)bufBitmap,
+ dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32,
+ 32, (int) (local.width * 4 - (unsigned) local.pitch), 32,
+ 0, 0, 0, NULL, { NULL }
+ };
+
+ XInitImage(&image);
+ XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, local.width, local.rows);
+ xftg->picture = XRenderCreatePicture(dpy, pixmap, font->format, 0, NULL);
+
+ XFreeGC(dpy, gc);
+ XFreePixmap(dpy, pixmap);
+ /*
+ * Record 256 times higher memory pressure for unrotated
+ * pictures, and maximum for rotated pictures.
+ */
+ if (font->info.matrix.xy || font->info.matrix.yx)
+ xftg->glyph_memory += font->max_glyph_memory - (unsigned long) size;
+ else
+ xftg->glyph_memory += (size_t)size * 255;
+ }
+ else
+ XRenderAddGlyphs (dpy, font->glyphset, &glyph,
+ &xftg->metrics, 1,
+ (char *) bufBitmap, size);
}
else
{
@@ -712,8 +1059,46 @@ XftFontLoadGlyphs (Display *dpy,
if (XftDebug() & XFT_DBG_CACHE)
_XftFontValidateMemory (dpy, pub);
if (XftDebug() & XFT_DBG_CACHEV)
- printf ("Caching glyph 0x%x size %ld\n", glyphindex,
+ printf ("Caching glyph 0x%x size %lu\n", glyphindex,
xftg->glyph_memory);
+
+ if (font->track_mem_usage) {
+ XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
+
+ if (font->newest == FT_UINT_MAX) {
+ xuse->older = glyphindex;
+ xuse->newer = glyphindex;
+ if (XftDebug() & XFT_DBG_USAGE)
+ printf("alloc %p -> %d: %p USE %d.%d\n",
+ (void *) font, glyphindex,
+ (void *) xuse, xuse->older, xuse->newer);
+ } else {
+ XftGlyphUsage *xnew;
+ XftGlyphUsage *xold;
+
+ assert(font->glyphs[font->newest] != NULL);
+ xnew = (XftGlyphUsage *) font->glyphs[font->newest];
+
+ assert(font->glyphs[xnew->newer] != NULL);
+ xold = (XftGlyphUsage *) font->glyphs[xnew->newer];
+
+ xuse->older = font->newest;
+ xuse->newer = xnew->newer;
+ xnew->newer = glyphindex;
+ xold->older = glyphindex;
+ if (XftDebug() & XFT_DBG_USAGE)
+ printf("alloc %p -> %d: %p USE %d.%d, %p NEW %d.%d %p OLD %d.%d\n",
+ (void *) font, glyphindex,
+ (void *) xuse, xuse->older, xuse->newer,
+ (void *) xnew, xnew->older, xnew->newer,
+ (void *) xold, xold->older, xold->newer);
+ }
+
+ font->newest = glyphindex;
+ font->total_inuse++;
+ if (XftDebug() & XFT_DBG_USAGE)
+ _XftValidateGlyphUsage(font);
+ }
}
if (bufBitmap != bufLocal)
free (bufBitmap);
@@ -742,9 +1127,14 @@ XftFontUnloadGlyphs (Display *dpy,
continue;
if (xftg->glyph_memory)
{
+ if (XftDebug() & XFT_DBG_CACHEV)
+ printf ("Uncaching glyph 0x%x size %lu\n",
+ glyphindex, xftg->glyph_memory);
if (font->format)
{
- if (font->glyphset)
+ if (xftg->picture)
+ XRenderFreePicture(dpy, xftg->picture);
+ else if (font->glyphset)
{
glyphBuf[nused++] = (Glyph) glyphindex;
if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0]))
@@ -754,17 +1144,52 @@ XftFontUnloadGlyphs (Display *dpy,
}
}
}
- else
- {
- if (xftg->bitmap)
- free (xftg->bitmap);
- }
+ else if (xftg->bitmap)
+ free (xftg->bitmap);
font->glyph_memory -= xftg->glyph_memory;
if (info)
info->glyph_memory -= xftg->glyph_memory;
}
+
+ if (font->track_mem_usage) {
+ XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
+ XftGlyphUsage *xtmp;
+
+ if (XftDebug() & XFT_DBG_USAGE)
+ printf("free %p -> %p USE %d.%d\n",
+ (void *) font, (void *) xuse, xuse->older, xuse->newer);
+
+ if (xuse->older != FT_UINT_MAX) {
+ xtmp = (XftGlyphUsage *) font->glyphs[xuse->older];
+ if (xtmp != NULL) {
+ /* update link around to oldest glyph */
+ xtmp->newer = xuse->newer;
+ }
+ if (font->newest == glyphindex) {
+ if (font->newest == xuse->older)
+ font->newest = FT_UINT_MAX;
+ else
+ font->newest = xuse->older;
+ }
+ }
+ if (xuse->newer != FT_UINT_MAX) {
+ xtmp = (XftGlyphUsage *) font->glyphs[xuse->newer];
+ if (xtmp != NULL) {
+ /* update link around to newest glyph */
+ xtmp->older = xuse->older;
+ }
+ }
+ if (font->total_inuse) {
+ font->total_inuse--;
+ } else {
+ fprintf (stderr, "Xft: glyph count error\n");
+ }
+ if (XftDebug() & XFT_DBG_USAGE)
+ _XftValidateGlyphUsage(font);
+ }
+
free (xftg);
- XftMemFree (XFT_MEM_GLYPH, sizeof (XftGlyph));
+ XftMemFree (XFT_MEM_GLYPH, font->sizeof_glyph);
font->glyphs[glyphindex] = NULL;
}
if (font->glyphset && nused)
@@ -790,13 +1215,21 @@ XftFontCheckGlyph (Display *dpy,
{
if (!xftg)
{
- xftg = (XftGlyph *) malloc (sizeof (XftGlyph));
+ xftg = malloc (font->sizeof_glyph);
if (!xftg)
return FcFalse;
- XftMemAlloc (XFT_MEM_GLYPH, sizeof (XftGlyph));
+ XftMemAlloc (XFT_MEM_GLYPH, font->sizeof_glyph);
+
xftg->bitmap = NULL;
xftg->glyph_memory = 0;
+ xftg->picture = 0;
font->glyphs[glyph] = xftg;
+
+ if (font->track_mem_usage) {
+ XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
+ xuse->older = FT_UINT_MAX;
+ xuse->newer = FT_UINT_MAX;
+ }
}
n = *nmissing;
missing[n++] = glyph;
@@ -808,14 +1241,46 @@ XftFontCheckGlyph (Display *dpy,
*nmissing = n;
return FcTrue;
}
- else
- return FcFalse;
+
+ /*
+ * Make unloading faster by moving newly-referenced glyphs to the front
+ * of the list, leaving the less-used glyphs on the end.
+ */
+ if (font->track_mem_usage
+ && font->total_inuse > 10
+ && font->newest != FT_UINT_MAX
+ && font->newest != glyph)
+ {
+ XftGlyphUsage *xuse = (XftGlyphUsage *) xftg;
+ XftGlyphUsage *xtmp = (XftGlyphUsage *) font->glyphs[font->newest];
+ XftGlyphUsage *xold;
+ XftGlyphUsage *xnew;
+
+ /* delink */
+ xold = (XftGlyphUsage *) font->glyphs[xuse->older];
+ xnew = (XftGlyphUsage *) font->glyphs[xuse->newer];
+ assert(xold != NULL);
+ assert(xnew != NULL);
+ xold->newer = xuse->newer;
+ xnew->older = xuse->older;
+
+ /* relink */
+ xnew = (XftGlyphUsage *) font->glyphs[xtmp->newer];
+ assert(xnew != NULL);
+ xnew->older = glyph;
+ xuse->older = font->newest;
+ xuse->newer = xtmp->newer;
+ xtmp->newer = glyph;
+
+ font->newest = glyph;
+ }
+ return FcFalse;
}
_X_EXPORT FcBool
-XftCharExists (Display *dpy,
+XftCharExists (Display *dpy _X_UNUSED,
XftFont *pub,
- FcChar32 ucs4)
+ FcChar32 ucs4)
{
if (pub->charset)
return FcCharSetHasChar (pub->charset, ucs4);
@@ -859,14 +1324,14 @@ XftCharIndex (Display *dpy,
offset = 1;
}
ent = ent + offset;
- if (ent >= font->hash_value)
+ if (ent >= (FcChar32)font->hash_value)
ent -= (FcChar32)font->hash_value;
}
return font->hash_table[ent].glyph;
}
/*
- * Pick a random glyph from the font and remove it from the cache
+ * Remove glyph(s) from the font to reduce memory-usage.
*/
_X_HIDDEN void
_XftFontUncacheGlyph (Display *dpy, XftFont *pub)
@@ -878,40 +1343,64 @@ _XftFontUncacheGlyph (Display *dpy, XftF
if (!font->glyph_memory)
return;
- if (font->use_free_glyphs)
+
+ if (XftDebug() & XFT_DBG_CACHE)
+ _XftFontValidateMemory (dpy, pub);
+
+ if (font->track_mem_usage)
{
+ /*
+ * Remove the oldest glyph from the font.
+ */
+ if (font->newest != FT_UINT_MAX) {
+ XftGlyphUsage *xuse = (XftGlyphUsage *) font->glyphs[font->newest];
+ if ((glyphindex = xuse->newer) != FT_UINT_MAX)
+ XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
+ }
+ }
+ else if (font->use_free_glyphs)
+ {
+ /*
+ * Pick a random glyph from the font and remove it from the cache
+ */
glyph_memory = ((unsigned long)rand() % font->glyph_memory);
+ for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
+ {
+ xftg = font->glyphs[glyphindex];
+ if (xftg)
+ {
+ if (xftg->glyph_memory > glyph_memory)
+ {
+ XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
+ break;
+ }
+ glyph_memory -= xftg->glyph_memory;
+ }
+ }
}
else
{
+ /*
+ * Free all glyphs, since they are part of a set.
+ */
if (font->glyphset)
{
XRenderFreeGlyphSet (dpy, font->glyphset);
font->glyphset = 0;
}
- glyph_memory = 0;
- }
-
- if (XftDebug() & XFT_DBG_CACHE)
- _XftFontValidateMemory (dpy, pub);
- for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
- {
- xftg = font->glyphs[glyphindex];
- if (xftg)
+ for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++)
{
- if (xftg->glyph_memory > glyph_memory)
+ xftg = font->glyphs[glyphindex];
+ if (xftg)
{
- if (XftDebug() & XFT_DBG_CACHEV)
- printf ("Uncaching glyph 0x%x size %ld\n",
- glyphindex, xftg->glyph_memory);
- XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
- if (!font->use_free_glyphs)
- continue;
- break;
+ if (xftg->glyph_memory > 0)
+ {
+ XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1);
+ }
}
- glyph_memory -= xftg->glyph_memory;
}
}
+
if (XftDebug() & XFT_DBG_CACHE)
_XftFontValidateMemory (dpy, pub);
}
@@ -926,7 +1415,7 @@ _XftFontManageMemory (Display *dpy, XftF
if (XftDebug() & XFT_DBG_CACHE)
{
if (font->glyph_memory > font->max_glyph_memory)
- printf ("Reduce memory for font 0x%lx from %ld to %ld\n",
+ printf ("Reduce memory for font 0x%lx from %lu to %lu\n",
font->glyphset ? font->glyphset : (unsigned long) font,
font->glyph_memory, font->max_glyph_memory);
}