[MPlayer-dev-eng] [PATCH] dynamic font generation

Jindrich Makovicka makovick at KMLinux.fjfi.cvut.cz
Mon Aug 19 18:17:30 CEST 2002


Here is an updated version of my previous patch. This one includes your
optimizations, and all the glyphs are now rendered on the fly, when they
appear first on the screen. The kerning info is now utilized too, to make
the subtitles look a bit better. Seems quite fine, only the font selection
from GUI still doesn't work.

-- 
Jindrich Makovicka
-------------- next part --------------
diff -urN --exclude-from dontdiff vanilla/main/DOCS/mplayer.1 main/DOCS/mplayer.1
--- vanilla/main/DOCS/mplayer.1	Mon Aug 12 18:21:07 2002
+++ main/DOCS/mplayer.1	Sun Aug 18 19:51:32 2002
@@ -613,6 +613,42 @@
 
 .I EXAMPLE:
     \-font ~/.mplayer/arial\-14/font.desc
+
+.I NOTE:
+    With FreeType, this option determines path to the text font file,
+eg.
+
+    -font ~/.mplayer/my_cool_font.ttf
+.TP
+.I NOTE:
+The -subfont-* options are available only with FreeType support
+compiled in.
+.TP
+.B \-subfont-encoding
+Sets the font encoding. When set to "unicode", all the glyphs from the
+font file will be rendered and unicode will be used. This is also the default.
+.TP
+.B \-subfont-text-scale
+Sets the subtitle text autoscale coefficient (percentage of the
+screen size).
+.TP
+.B \-subfont-osd-scale
+Sets the osd elements autoscale coefficient.
+.TP
+.B \-subfont-blur
+Sets the font blur radius.
+.TP
+.B \-subfont-outline
+Sets the font outline thickness.
+.TP
+.B \-subfont-autoscale <0-3>
+Sets the autoscale mode. Can be
+    0    no autoscale,
+    1    proportional to movie width,
+    2    proportional to movie height,
+    3    proportional to movie diagonal.
+
+Default is 3 (diagonal).
 .TP
 .B \-noautosub
 Turns off automatic subtitles.
diff -urN --exclude-from dontdiff vanilla/main/Gui/Makefile main/Gui/Makefile
--- vanilla/main/Gui/Makefile	Sun Aug 11 18:29:33 2002
+++ main/Gui/Makefile	Sun Aug 18 19:58:09 2002
@@ -4,7 +4,7 @@
 include ../config.mak
 include config.mak
 
-INCDIR  = -I. -I./event -I./wm -I./skin $(GTKINC) $(EXTRA_INC)
+INCDIR  = -I. -I./event -I./wm -I./skin $(GTKINC) $(EXTRA_INC) $(FREETYPE_INC)
 
 OPTIMIZE =  $(OPTFLAGS) -fomit-frame-pointer \
             -fexpensive-optimizations -fschedule-insns2 -Wall
diff -urN --exclude-from dontdiff vanilla/main/Gui/interface.c main/Gui/interface.c
--- vanilla/main/Gui/interface.c	Mon Aug 12 18:21:22 2002
+++ main/Gui/interface.c	Sun Aug 18 19:46:22 2002
@@ -149,6 +149,11 @@
 void guiLoadFont( void )
 {
  font_factor=gtkSubFFactor;
+#ifdef HAVE_FREETYPE 
+
+ /* FIXME */
+ 
+#else
  if ( vo_font )
   {
    int i;
@@ -183,6 +188,7 @@
       vo_font=read_font_desc( guiIntfStruct.Fontname,font_factor,0 );
      }
    }
+#endif
 }
 #endif
 
diff -urN --exclude-from dontdiff vanilla/main/Makefile main/Makefile
--- vanilla/main/Makefile	Sun Aug 11 10:18:13 2002
+++ main/Makefile	Wed Aug 14 11:29:10 2002
@@ -32,7 +32,7 @@
 INSTALL = install
 
 SRCS_COMMON = xacodec.c cpudetect.c codec-cfg.c cfgparser.c my_profile.c spudec.c playtree.c playtreeparser.c asxparser.c vobsub.c subreader.c sub_cc.c find_sub.c
-SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c me-opt-reg.c
+SRCS_MENCODER = mencoder.c mp_msg-mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/osd.c libvo/sub.c libvo/font_load.c libvo/font_load_ttf.c me-opt-reg.c
 SRCS_MPLAYER = mplayer.c mp_msg.c $(SRCS_COMMON) lirc_mp.c mixer.c mp-opt-reg.c
 
 OBJS_MENCODER = $(SRCS_MENCODER:.c=.o)
@@ -51,11 +51,11 @@
 A_LIBS = $(ALSA_LIB) $(ARTS_LIB) $(NAS_LIB) $(MAD_LIB) $(VORBIS_LIB) $(FAAD_LIB) $(SGIAUDIO_LIB)
 
 CODEC_LIBS = -Llibmpcodecs -lmpcodecs -Lmp3lib -lMP3 -Lliba52 -la52 -Llibmpeg2 -lmpeg2 $(AV_LIB) $(FAME_LIB) $(XVID_LIB)
-COMMON_LIBS = $(CODEC_LIBS) -Llibmpdemux -lmpdemux  $(NEW_INPUT_LIB)  $(LIB_LOADER) $(A_LIBS) $(CSS_LIB) $(ARCH_LIB) -Lpostproc -lpostproc $(DECORE_LIB) -Llinux -losdep $(TERMCAP_LIB)  $(STREAMING_LIB) $(Z_LIB) $(GTK_LIBS) $(PNG_LIB) $(JPEG_LIB) $(GIF_LIB) $(CDPARANOIA_LIB) -lm
+COMMON_LIBS = $(CODEC_LIBS) -Llibmpdemux -lmpdemux  $(NEW_INPUT_LIB)  $(LIB_LOADER) $(A_LIBS) $(CSS_LIB) $(ARCH_LIB) -Lpostproc -lpostproc $(DECORE_LIB) -Llinux -losdep $(TERMCAP_LIB)  $(STREAMING_LIB) $(Z_LIB) $(GTK_LIBS) $(PNG_LIB) $(JPEG_LIB) $(GIF_LIB) $(CDPARANOIA_LIB) $(FREETYPE_LIB) -lm
 ifeq ($(VIDIX),yes)
 MISC_LIBS += -Llibdha -ldha -Lvidix -lvidix
 endif
-CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader $(VO_INC) $(EXTRA_INC) $(CDPARANOIA_INC)# -Wall
+CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader $(VO_INC) $(EXTRA_INC) $(CDPARANOIA_INC) $(FREETYPE_INC) # -Wall
 
 PARTS = libfame libmpdemux libmpcodecs mp3lib liba52 libmp1e libmpeg2 libavcodec libao2 drivers linux postproc input libmpdvdkit
 ifeq ($(VIDIX),yes)
diff -urN --exclude-from dontdiff vanilla/main/cfg-common.h main/cfg-common.h
--- vanilla/main/cfg-common.h	Tue Aug  6 19:04:55 2002
+++ main/cfg-common.h	Mon Aug 19 09:25:50 2002
@@ -163,6 +163,14 @@
 	{"font", &font_name, CONF_TYPE_STRING, 0, 0, 0, NULL},
 	{"ffactor", &font_factor, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 10.0, NULL},
  	{"subpos", &sub_pos, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL},
+#ifdef HAVE_FREETYPE
+	{"subfont-encoding", &subtitle_font_encoding, CONF_TYPE_STRING, 0, 0, 0, NULL},
+ 	{"subfont-text-scale", &text_font_scale_factor, CONF_TYPE_FLOAT, CONF_RANGE, 0, 100, NULL},
+ 	{"subfont-osd-scale", &osd_font_scale_factor, CONF_TYPE_FLOAT, CONF_RANGE, 0, 100, NULL},
+ 	{"subfont-blur", &subtitle_font_radius, CONF_TYPE_FLOAT, CONF_RANGE, 0, 8, NULL},
+ 	{"subfont-outline", &subtitle_font_thickness, CONF_TYPE_FLOAT, CONF_RANGE, 0, 8, NULL},
+ 	{"subfont-autoscale", &subtitle_autoscale, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL},
+#endif
 #endif
 
 #else
diff -urN --exclude-from dontdiff vanilla/main/configure main/configure
--- vanilla/main/configure	Mon Aug 12 18:20:19 2002
+++ main/configure	Wed Aug 14 13:48:00 2002
@@ -168,6 +168,7 @@
   --disable-cdparanoia   Disable cdparanoia support [autodetect]
   --disable-big-endian   Force byte order to little endian [autodetect]
   --enable-big-endian    Force byte order to big endian [autodetect]
+  --disable-freetype     Disable freetype support [autodetect]
   
 Video:
   --enable-gl            build with OpenGL render support [autodetect]
@@ -979,6 +980,7 @@
 _libdv=auto
 _cdparanoia=auto
 _big_endian=auto
+_freetype=auto
 
 for ac_option do
   case "$ac_option" in
@@ -1139,6 +1141,8 @@
   --disable-cdparanoia)	_cdparanoia=no	;;
   --enable-big-endian)  _big_endian=yes ;;
   --disable-big-endian) _big_endian=no  ;;
+  --enable-freetype)    _freetype=yes   ;;
+  --disable-freetype)   _freetype=no    ;;
 
   --enable-dga) _dga=auto ;; # as we don't know if it's 1 or 2
   --enable-dga=*) _dga=`echo $ac_option | cut -d '=' -f 2` ;;
@@ -3125,7 +3129,7 @@
 int main(void) { return 1; }
 EOF
     _cdparanoia=no
-    cc_check $_inc_cdparnoia $_ld_cdparanoia -lcdda_interface -lcdda_paranoia && _cdparanoia=yes
+    cc_check $_inc_cdparanoia $_ld_cdparanoia -lcdda_interface -lcdda_paranoia && _cdparanoia=yes
 fi
 if test "$_cdparanoia" = yes ; then
     _def_cdparanoia='#define HAVE_CDDA'
@@ -3137,6 +3141,23 @@
 fi
 echores "$_cdparanoia"
 
+echocheck "freetype"
+if test "$_freetype" = auto ; then
+    if ( freetype-config --version ) >/dev/null 2>&1 ; then
+	_freetype=yes
+    else
+	_freetype=no
+    fi
+fi
+if test "$_freetype" = yes ; then
+    _def_freetype='#define HAVE_FREETYPE'
+    _inc_freetype=`freetype-config --cflags`
+    _ld_freetype=`freetype-config --libs`
+else
+    _def_freetype='#undef HAVE_FREETYPE'
+fi
+echores "$_freetype"
+
 echocheck "zlib"
 cat > $TMPC << EOF
 #include <zlib.h>
@@ -4224,6 +4245,8 @@
 NEW_INPUT_LIB = $_ld_new_input
 CDPARANOIA_INC = $_inc_cdparnoia
 CDPARANOIA_LIB = $_ld_cdparanoia
+FREETYPE_INC = $_inc_freetype
+FREETYPE_LIB = $_ld_freetype
 
 # --- Some stuff for autoconfigure ----
 $_target_arch
@@ -4549,6 +4572,9 @@
 /* enable GIF support */
 $_def_gif
 $_def_gif_4
+
+/* enable FreeType support */
+$_def_freetype
 
 /* libmad support */
 $_def_mad
diff -urN --exclude-from dontdiff vanilla/main/libvo/Makefile main/libvo/Makefile
--- vanilla/main/libvo/Makefile	Sun Jun 16 16:03:54 2002
+++ main/libvo/Makefile	Wed Aug 14 09:24:51 2002
@@ -3,14 +3,14 @@
 
 LIBNAME = libvo.a
 
-SRCS=aspect.c aclib.c osd.c font_load.c spuenc.c video_out.c vo_null.c vo_pgm.c vo_md5.c vo_mpegpes.c vo_yuv4mpeg.c $(OPTIONAL_SRCS) sub.c
+SRCS=aspect.c aclib.c osd.c font_load.c spuenc.c video_out.c vo_null.c vo_pgm.c vo_md5.c vo_mpegpes.c vo_yuv4mpeg.c $(OPTIONAL_SRCS) sub.c font_load_ttf.c
 OBJS=$(SRCS:.c=.o)
 
 ifeq ($(VIDIX),yes)
 SRCS += vosub_vidix.c
 endif
 
-CFLAGS  = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC) $(DXR2_INC) $(DVB_INC) $(DIRECTFB_INC) -DMPG12PLAY #-Wall
+CFLAGS  = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC) $(DXR2_INC) $(DVB_INC) $(DIRECTFB_INC) $(FREETYPE_INC) -DMPG12PLAY #-Wall
 ifeq ($(VIDIX),yes)
 CFLAGS += -DVIDIX_PATH='"$(prefix)/lib/mplayer/vidix/"'
 endif
diff -urN --exclude-from dontdiff vanilla/main/libvo/font_load.c main/libvo/font_load.c
--- vanilla/main/libvo/font_load.c	Thu May  2 03:56:00 2002
+++ main/libvo/font_load.c	Wed Aug 14 09:06:31 2002
@@ -1,3 +1,6 @@
+#include "config.h"
+
+#ifndef HAVE_FREETYPE
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,7 +9,6 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "config.h"
 #include "font_load.h"
 
 extern char *get_path ( char * );
@@ -300,3 +302,5 @@
 
 }
 #endif
+
+#endif /* HAVE_FREETYPE */
diff -urN --exclude-from dontdiff vanilla/main/libvo/font_load.h main/libvo/font_load.h
--- vanilla/main/libvo/font_load.h	Thu May  2 03:56:00 2002
+++ main/libvo/font_load.h	Mon Aug 19 09:56:42 2002
@@ -1,8 +1,15 @@
+#ifdef HAVE_FREETYPE
+#include <freetype/freetype.h>
+#endif
 
 typedef struct {
     unsigned char *bmp;
     unsigned char *pal;
     int w,h,c;
+#ifdef HAVE_FREETYPE
+    int charwidth,charheight,pen,baseline,padding;
+    int current_count, current_alloc;
+#endif
 } raw_file;
 
 typedef struct {
@@ -18,9 +25,67 @@
     short font[65536];
     int start[65536];   // short is not enough for unicode fonts
     short width[65536];
+
+#ifdef HAVE_FREETYPE
+    int face_cnt;
+    
+    FT_Face faces[16];
+    FT_UInt glyph_index[65536];
+
+    int max_width, max_height;
+
+    struct 
+    {
+	int g_r;
+	int o_r;
+	int g_w;
+	int o_w;
+	int o_size;
+	unsigned volume;
+
+	unsigned *g;
+	unsigned *gt;
+	unsigned *gt2;
+	unsigned *om;
+	unsigned char *omt;
+	unsigned short *tmp;
+    } tables;
+#endif
+
 } font_desc_t;
 
 extern font_desc_t* vo_font;
 
+#ifdef HAVE_FREETYPE
+
+extern char *subtitle_font_encoding;
+extern float text_font_scale_factor;
+extern float osd_font_scale_factor;
+extern float subtitle_font_radius;
+extern float subtitle_font_thickness;
+extern int subtitle_autoscale;
+
+int init_freetype();
+int done_freetype();
+
+font_desc_t* read_font_desc(char* fname,float factor,int movie_width, int movie_height);
+void free_font_desc(font_desc_t *desc);
+
+void render_one_glyph(font_desc_t *desc, int c);
+int kerning(font_desc_t *desc, int prevc, int c);
+
+#else
+
 raw_file* load_raw(char *name,int verbose);
 font_desc_t* read_font_desc(char* fname,float factor,int verbose);
+
+void inline render_one_glyph(font_desc_t *desc, int c) 
+{
+}
+
+int inline render_one_glyph(font_desc_t *desc, int c) 
+{
+    return 0;
+}
+
+#endif
diff -urN --exclude-from dontdiff vanilla/main/libvo/font_load_ttf.c main/libvo/font_load_ttf.c
--- vanilla/main/libvo/font_load_ttf.c	Thu Jan  1 01:00:00 1970
+++ main/libvo/font_load_ttf.c	Mon Aug 19 10:18:20 2002
@@ -0,0 +1,1050 @@
+/*
+ * Renders antialiased fonts for mplayer using freetype library.
+ * Should work with TrueType, Type1 and any other font supported by libfreetype.
+ *
+ * Artur Zaprzala <zybi at fanthom.irc.pl>
+ *
+ * ported inside mplayer by Jindrich Makovicka 
+ * <makovick at kmlinux.fjfi.cvut.cz>
+ *
+ */
+
+#include "config.h"
+
+#ifdef HAVE_FREETYPE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iconv.h>
+#include <math.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
+
+#include "../bswap.h"
+#include "font_load.h"
+#include "mp_msg.h"
+#include "../mplayer.h"
+
+char *get_path(char *filename);
+
+char *subtitle_font_encoding = NULL;
+float text_font_scale_factor = 5.0;
+float osd_font_scale_factor = 6.0;
+float subtitle_font_radius = 2.0;
+float subtitle_font_thickness = 2.0;
+// 0 = no autoscale
+// 1 = video height
+// 2 = video width
+// 3 = diagonal
+int subtitle_autoscale = 3;
+
+//// constants
+static int const colors = 256;
+static int const maxcolor = 255;
+static unsigned const	base = 256;
+static unsigned const first_char = 33;
+#define MAX_CHARSET_SIZE 60000
+
+static FT_Library library;
+
+#define OSD_CHARSET_SIZE 15
+
+static FT_ULong	osd_charset[OSD_CHARSET_SIZE] =
+{
+    0xe001, 0xe002, 0xe003, 0xe004, 0xe005, 0xe006, 0xe007, 0xe008,
+    0xe009, 0xe00a, 0xe00b, 0xe010, 0xe011, 0xe012, 0xe013
+};
+
+static FT_ULong	osd_charcodes[OSD_CHARSET_SIZE] =
+{
+    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
+    0x09,0x0a,0x0b,0x10,0x11,0x12,0x13
+};
+
+#define f266ToInt(x)		(((x)+32)>>6)	// round fractional fixed point number to integer
+						// coordinates are in 26.6 pixels (i.e. 1/64th of pixels)
+#define f266CeilToInt(x)	(((x)+63)>>6)	// ceiling
+#define f266FloorToInt(x)	((x)>>6)	// floor
+#define f1616ToInt(x)		(((x)+0x8000)>>16)	// 16.16
+#define floatTof266(x)		((int)((x)*(1<<6)+0.5))
+
+#define ALIGN(x)                (((x)+7)&~7)    // 8 byte align
+
+#define WARNING(msg, args...)      mp_msg(MSGT_OSD, MSGL_WARN, msg "\n", ## args)
+
+#define DEBUG 0
+
+//static double ttime;
+
+
+static void paste_bitmap(unsigned char *bbuffer, FT_Bitmap *bitmap, int x, int y, int width, int height, int bwidth) {
+    int drow = x+y*width;
+    int srow = 0;
+    int sp, dp, w, h;
+    if (bitmap->pixel_mode==ft_pixel_mode_mono)
+	for (h = bitmap->rows; h>0 && height > 0; --h, height--, drow+=width, srow+=bitmap->pitch)
+	    for (w = bwidth, sp=dp=0; w>0; --w, ++dp, ++sp)
+		    bbuffer[drow+dp] = (bitmap->buffer[srow+sp/8] & (0x80>>(sp%8))) ? 255:0;
+    else
+	for (h = bitmap->rows; h>0 && height > 0; --h, height--, drow+=width, srow+=bitmap->pitch)
+	    for (w = bwidth, sp=dp=0; w>0; --w, ++dp, ++sp)
+		    bbuffer[drow+dp] = bitmap->buffer[srow+sp];
+}
+
+
+static int check_font(font_desc_t *desc, float ppem, int padding, int pic_idx,
+		      int charset_size, FT_ULong *charset, FT_ULong *charcodes,
+		      int unicode) {
+    FT_Error	error;
+    FT_Face face = desc->faces[pic_idx];
+    int	const	load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
+    int		ymin = INT_MAX, ymax = INT_MIN;
+    int		baseline, space_advance = 20;
+    int         width, height;
+    unsigned char *bbuffer;
+    int i, uni_charmap = 1;
+    
+
+    if (face->charmap==NULL || face->charmap->encoding!=ft_encoding_unicode) {
+	WARNING("Unicode charmap not available for this font. Very bad!");
+	uni_charmap = 0;
+	error = FT_Set_Charmap(face, face->charmaps[0]);
+	if (error) WARNING("No charmaps! Strange.");
+    }
+
+    /* set size */
+    if (FT_IS_SCALABLE(face)) {
+	error = FT_Set_Char_Size(face, 0, floatTof266(ppem), 0, 0);
+	if (error) WARNING("FT_Set_Char_Size failed.");
+    } else {
+	int j = 0;
+	int jppem = face->available_sizes[0].height;
+	/* find closest size */
+	for (i = 0; i<face->num_fixed_sizes; ++i) {
+	    if (fabs(face->available_sizes[i].height - ppem) < abs(face->available_sizes[i].height - jppem)) {
+		j = i;
+		jppem = face->available_sizes[i].height;
+	    }
+	}
+	WARNING("Selected font is not scalable. Using ppem=%i.", face->available_sizes[j].height);
+	error = FT_Set_Pixel_Sizes(face, face->available_sizes[j].width, face->available_sizes[j].height);
+	if (error) WARNING("FT_Set_Pixel_Sizes failed.");
+    }
+
+    if (FT_IS_FIXED_WIDTH(face))
+	WARNING("Selected font is fixed-width.");
+
+    /* compute space advance */
+    error = FT_Load_Char(face, ' ', load_flags);
+    if (error) WARNING("spacewidth set to default.");
+    else space_advance = f266ToInt(face->glyph->advance.x);
+
+    if (!desc->spacewidth) desc->spacewidth = 2*padding + space_advance;
+    if (!desc->charspace) desc->charspace = -2*padding;
+    if (!desc->height) desc->height = f266ToInt(face->size->metrics.height);
+
+
+    for (i= 0; i<charset_size; ++i) {
+	FT_ULong	character, code;
+	FT_UInt		glyph_index;
+
+	character = charset[i];
+	code = charcodes[i];
+	desc->font[unicode?character:code] = pic_idx;
+	// get glyph index
+	if (character==0)
+	    glyph_index = 0;
+	else {
+	    glyph_index = FT_Get_Char_Index(face, uni_charmap ? character:code);
+	    if (glyph_index==0) {
+		WARNING("Glyph for char 0x%02x|U+%04X|%c not found.", code, character,
+			code<' '||code>255 ? '.':code);
+		desc->font[unicode?character:code] = -1;
+		continue;
+	    }
+	}
+	desc->glyph_index[unicode?character:code] = glyph_index;
+    }
+//    fprintf(stderr, "font height: %lf\n", (double)(face->bbox.yMax-face->bbox.yMin)/(double)face->units_per_EM*ppem);
+//    fprintf(stderr, "font width: %lf\n", (double)(face->bbox.xMax-face->bbox.xMin)/(double)face->units_per_EM*ppem);
+
+    ymax = (double)(face->bbox.yMax)/(double)face->units_per_EM*ppem+1;
+    ymin = (double)(face->bbox.yMin)/(double)face->units_per_EM*ppem-1;
+    
+    width = ppem*(face->bbox.xMax-face->bbox.xMin)/face->units_per_EM+3+2*padding;
+    if (desc->max_width < width) desc->max_width = width;
+    width = ALIGN(width);
+    desc->pic_b[pic_idx]->charwidth = width;
+
+    if (ymax<=ymin) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "Something went wrong. Use the source!\n");
+	return -1;
+    }
+    
+    height = ymax - ymin + 2*padding;
+    if (desc->max_height < height) desc->max_height = height;
+    desc->pic_b[pic_idx]->charheight = height;
+    
+//    fprintf(stderr, "font height2: %d\n", height);
+    desc->pic_b[pic_idx]->baseline = ymax + padding;
+    desc->pic_b[pic_idx]->padding = padding;
+    desc->pic_b[pic_idx]->current_alloc = 0;
+    desc->pic_b[pic_idx]->current_count = 0;
+
+    bbuffer = NULL;
+    
+    desc->pic_b[pic_idx]->w = width;
+    desc->pic_b[pic_idx]->h = height;
+    desc->pic_b[pic_idx]->c = colors;
+    desc->pic_b[pic_idx]->bmp = bbuffer;
+    desc->pic_b[pic_idx]->pen = 0;
+    return 0;
+}
+
+// general outline
+void outline(
+	unsigned char *s,
+	unsigned char *t,
+	int width,
+	int height,
+	int stride,
+	unsigned char *m,
+	int r,
+	int mwidth,
+	int msize) {
+
+    int x, y;
+    
+    for (y = 0; y<height; y++) {
+	for (x = 0; x<width; x++) {
+	    const int src= s[x];
+	    if(src==0) continue;
+	    {
+		const int x1=(x<r) ? r-x : 0;
+		const int y1=(y<r) ? r-y : 0;
+		const int x2=(x+r>=width ) ? r+width -x : 2*r+1;
+		const int y2=(y+r>=height) ? r+height-y : 2*r+1;
+		register unsigned char *dstp= t + (y1+y-r)* stride + x-r;
+		//register int *mp  = m +  y1     *mwidth;
+		register unsigned char *mp= m + msize*src + y1*mwidth;
+		int my;
+
+		for(my= y1; my<y2; my++){
+		    register int mx;
+		    for(mx= x1; mx<x2; mx++){
+			if(dstp[mx] < mp[mx]) dstp[mx]= mp[mx];
+		    }
+		    dstp+=stride;
+		    mp+=mwidth;
+		}
+            }
+	}
+	s+= stride;
+    }
+}
+
+
+// 1 pixel outline
+void outline1(
+	unsigned char *s,
+	unsigned char *t,
+	int width,
+	int height,
+	int stride) {
+
+    int x, y, mx, my;
+    int skip = stride-width;
+
+    for (x = 0; x<width; ++x, ++s, ++t) *t = *s;
+    s += skip;
+    t += skip;
+    for (y = 1; y<height-1; ++y) {
+	*t++ = *s++;
+	for (x = 1; x<width-1; ++x, ++s, ++t) {
+	    unsigned v = (
+		    s[-1-stride]+
+		    s[-1+stride]+
+		    s[+1-stride]+
+		    s[+1+stride]
+		)/2 + (
+		    s[-1]+
+		    s[+1]+
+		    s[-stride]+
+		    s[+stride]+
+		    s[0]
+		);
+	    *t = v>maxcolor ? maxcolor : v;
+	}
+	*t++ = *s++;
+	s += skip;
+	t += skip;
+    }
+    for (x = 0; x<width; ++x, ++s, ++t) *t = *s;
+}
+
+
+// gaussian blur
+void blur(
+	unsigned char *buffer,
+	unsigned short *tmp2,
+	int width,
+	int height,
+	int stride,
+	int *m,
+	int *m2,
+	int r,
+	int mwidth,
+	unsigned volume) {
+
+    int x, y;
+
+    unsigned char  *s = buffer;
+    unsigned short *t = tmp2+1;
+    for(y=0; y<height; y++){
+	memset(t-1, 0, (width+1)*sizeof(short));
+
+	for(x=0; x<r; x++){
+	    const int src= s[x];
+	    if(src){
+		register unsigned short *dstp= t + x-r;
+		int mx;
+		unsigned *m3= m2 + src*mwidth;
+		for(mx=r-x; mx<mwidth; mx++){
+		    dstp[mx]+= m3[mx];
+		}
+	    }
+	}
+
+	for(; x<width-r; x++){
+	    const int src= s[x];
+	    if(src){
+		register unsigned short *dstp= t + x-r;
+		int mx;
+		unsigned *m3= m2 + src*mwidth;
+		for(mx=0; mx<mwidth; mx++){
+		    dstp[mx]+= m3[mx];
+		}
+	    }
+	}
+
+	for(; x<width; x++){
+	    const int src= s[x];
+	    if(src){
+		register unsigned short *dstp= t + x-r;
+		int mx;
+		const int x2= r+width -x;
+		const int off= src*mwidth;
+		unsigned *m3= m2 + src*mwidth;
+		for(mx=0; mx<x2; mx++){
+		    dstp[mx]+= m3[mx];
+		}
+	    }
+	}
+
+	s+= stride;
+	t+= width + 1;
+    }
+
+    t = tmp2;
+    for(x=0; x<width; x++){
+	for(y=0; y<r; y++){
+	    unsigned short *srcp= t + y*(width+1) + 1;
+	    int src= *srcp;
+	    if(src){
+		register unsigned short *dstp= srcp - 1 + width+1;
+		const int src2= (src + 128)>>8;
+		unsigned *m3= m2 + src2*mwidth;
+
+		int mx;
+		*srcp= 128;
+		for(mx=r-1; mx<mwidth; mx++){
+		    *dstp += m3[mx];
+		    dstp+= width+1;
+		}
+	    }
+	}
+	for(; y<height-r; y++){
+	    unsigned short *srcp= t + y*(width+1) + 1;
+	    int src= *srcp;
+	    if(src){
+		register unsigned short *dstp= srcp - 1 - r*(width+1);
+		const int src2= (src + 128)>>8;
+		unsigned *m3= m2 + src2*mwidth;
+
+		int mx;
+		*srcp= 128;
+		for(mx=0; mx<mwidth; mx++){
+		    *dstp += m3[mx];
+		    dstp+= width+1;
+		}
+	    }
+	}
+	for(; y<height; y++){
+	    unsigned short *srcp= t + y*(width+1) + 1;
+	    int src= *srcp;
+	    if(src){
+		const int y2=r+height-y;
+		register unsigned short *dstp= srcp - 1 - r*(width+1);
+		const int src2= (src + 128)>>8;
+		unsigned *m3= m2 + src2*mwidth;
+
+		int mx;
+		*srcp= 128;
+		for(mx=0; mx<y2; mx++){
+		    *dstp += m3[mx];
+		    dstp+= width+1;
+		}
+	    }
+	}
+	t++;
+    }
+
+    t = tmp2;
+    s = buffer;
+    for(y=0; y<height; y++){
+	for(x=0; x<width; x++){
+	    s[x]= t[x]>>8;
+	}
+	s+= stride;
+	t+= width + 1;
+    }
+}
+
+// Gaussian matrix
+static unsigned gmatrix(unsigned char *m, int r, int w, double const A) {
+    unsigned volume = 0;		// volume under Gaussian area is exactly -pi*base/A
+    int mx, my;
+
+    for (my = 0; my<w; ++my) {
+	for (mx = 0; mx<w; ++mx) {
+	    m[mx+my*w] = (exp(A * ((mx-r)*(mx-r)+(my-r)*(my-r))) * base + .5);
+	    volume+= m[mx+my*w];
+	}
+    }
+    mp_msg(MSGT_OSD, MSGL_DBG2, "A= %f\n", A);
+    mp_msg(MSGT_OSD, MSGL_DBG2, "volume: %i; exact: %.0f; volume/exact: %.6f\n\n", volume, -M_PI*base/A, volume/(-M_PI*base/A));
+    return volume;
+}
+
+static void resample_alpha(unsigned char *abuf, unsigned char *bbuf, int width, int height, int stride, float factor)
+{
+        int f=factor*256.0f;
+        int i,j;
+	for (i = 0; i < height; i++) {
+	    unsigned char *a = abuf+i*stride;
+	    unsigned char *b = bbuf+i*stride;
+	    for(j=0;j<width;j++,a++,b++){
+		int x=*a;	// alpha
+		int y=*b;	// bitmap
+		x=255-((x*f)>>8); // scale
+		if (x+y>255) x=255-y; // to avoid overflows
+		if (x<1) x=1; else if (x>=252) x=0;
+		*a=x;
+	    }
+	}
+}
+
+#define ALLOC_INCR 32
+void render_one_glyph(font_desc_t *desc, int c)
+{
+    FT_GlyphSlot	slot;
+    FT_ULong	character, code;
+    FT_UInt		glyph_index;
+    FT_BBox		bbox;
+    FT_BitmapGlyph glyph;
+    int width, height, stride, maxw, off;
+    unsigned char *abuffer, *bbuffer;
+    
+    int	const	load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
+    int		pen_xa;
+    int font = desc->font[c];
+    int error;
+    
+    if (desc->width[c] != -1) return;
+    if (desc->font[c] == -1) return;
+
+//    fprintf(stderr, "render_one_glyph %d\n", c);
+
+    glyph_index = desc->glyph_index[c];
+    
+    // load glyph
+    error = FT_Load_Glyph(desc->faces[font], glyph_index, load_flags);
+    if (error) {
+	WARNING("FT_Load_Glyph 0x%02x (char 0x%02x|U+%04X) failed.", glyph_index, code, character);
+	desc->font[c] = -1;
+	return;
+    }
+    slot = desc->faces[font]->glyph;
+
+    // render glyph
+    if (slot->format != ft_glyph_format_bitmap) {
+	error = FT_Render_Glyph(slot, ft_render_mode_normal);
+	if (error) {
+	    WARNING("FT_Render_Glyph 0x%04x (char 0x%02x|U+%04X) failed.", glyph_index, code, character);
+	    desc->font[c] = -1;
+	    return;
+	}
+    }
+
+    // extract glyph image
+    error = FT_Get_Glyph(slot, (FT_Glyph*)&glyph);
+    if (error) {
+	WARNING("FT_Get_Glyph 0x%04x (char 0x%02x|U+%04X) failed.", glyph_index, code, character);
+	desc->font[c] = -1;
+	return;
+    }
+
+//    fprintf(stderr, "glyph generated\n");
+
+    maxw = desc->pic_b[font]->charwidth;
+    
+    if (glyph->bitmap.width > maxw) {
+	fprintf(stderr, "glyph too wide!\n");
+    }
+
+    // allocate new memory, if needed
+    if (desc->pic_b[font]->current_count >= desc->pic_b[font]->current_alloc) {
+	int newsize = desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight*(desc->pic_b[font]->current_alloc+ALLOC_INCR);
+	int increment = desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight*ALLOC_INCR;
+	desc->pic_b[font]->current_alloc += ALLOC_INCR;
+
+	desc->pic_b[font]->bmp = realloc(desc->pic_b[font]->bmp, newsize);
+	desc->pic_a[font]->bmp = realloc(desc->pic_a[font]->bmp, newsize);
+
+	off = desc->pic_b[font]->current_count*desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight;
+	memset(desc->pic_b[font]->bmp+off, 0, increment);
+	memset(desc->pic_a[font]->bmp+off, 0, increment);
+    }
+    
+    abuffer = desc->pic_a[font]->bmp;
+    bbuffer = desc->pic_b[font]->bmp;
+
+    off = desc->pic_b[font]->current_count*desc->pic_b[font]->charwidth*desc->pic_b[font]->charheight;
+
+    paste_bitmap(bbuffer+off,
+		 &glyph->bitmap,
+		 desc->pic_b[font]->padding + glyph->left,
+		 desc->pic_b[font]->baseline - glyph->top,
+		 desc->pic_b[font]->charwidth, desc->pic_b[font]->charheight,
+		 glyph->bitmap.width <= maxw ? glyph->bitmap.width : maxw);
+    
+//    fprintf(stderr, "glyph pasted\n");
+    FT_Done_Glyph((FT_Glyph)glyph);
+    
+    /* advance pen */
+    pen_xa = f266ToInt(slot->advance.x) + 2*desc->pic_b[font]->padding;
+    if (pen_xa > maxw) pen_xa = maxw;
+
+    desc->start[c] = off;
+    width = desc->width[c] = pen_xa;
+    height = desc->pic_b[font]->charheight;
+    stride = desc->pic_b[font]->w;
+
+    if (desc->tables.o_r <= 1) {
+	outline1(bbuffer+off, abuffer+off, width, height, stride);
+    } else {
+	outline(bbuffer+off, abuffer+off, width, height, stride,
+		desc->tables.omt, desc->tables.o_r, desc->tables.o_w,
+		desc->tables.o_size);
+    }
+//    fprintf(stderr, "fg: outline t = %lf\n", GetTimer()-t);
+    
+    if (desc->tables.g_r) {
+	blur(abuffer+off, desc->tables.tmp, width, height, stride,
+	     desc->tables.gt, desc->tables.gt2, desc->tables.g_r,
+	     desc->tables.g_w, desc->tables.volume);
+//	fprintf(stderr, "fg: blur t = %lf\n", GetTimer()-t);
+    }
+
+    resample_alpha(abuffer+off, bbuffer+off, width, height, stride, font_factor);
+
+    desc->pic_b[font]->current_count++;
+}
+
+
+static int prepare_font(font_desc_t *desc, FT_Face face, float ppem, int pic_idx,
+			int charset_size, FT_ULong *charset, FT_ULong *charcodes, int unicode,
+			double thickness, double radius)
+{
+    int i, err;
+    int padding = ceil(radius) + ceil(thickness);
+
+    desc->faces[pic_idx] = face;
+
+    desc->pic_a[pic_idx] = (raw_file*)malloc(sizeof(raw_file));
+    if (!desc->pic_a[pic_idx]) return -1;
+    desc->pic_b[pic_idx] = (raw_file*)malloc(sizeof(raw_file));
+    if (!desc->pic_b[pic_idx]) return -1;
+
+    desc->pic_a[pic_idx]->bmp = NULL;
+    desc->pic_a[pic_idx]->pal = NULL;
+    desc->pic_b[pic_idx]->bmp = NULL;
+    desc->pic_b[pic_idx]->pal = NULL;
+
+    desc->pic_a[pic_idx]->pal = (unsigned char*)malloc(sizeof(unsigned char)*256*3);
+    if (!desc->pic_a[pic_idx]->pal) return -1;
+    for (i = 0; i<768; ++i) desc->pic_a[pic_idx]->pal[i] = i/3;
+
+    desc->pic_b[pic_idx]->pal = (unsigned char*)malloc(sizeof(unsigned char)*256*3);
+    if (!desc->pic_b[pic_idx]->pal) return -1;
+    for (i = 0; i<768; ++i) desc->pic_b[pic_idx]->pal[i] = i/3;
+
+//    ttime = GetTimer();
+    err = check_font(desc, ppem, padding, pic_idx, charset_size, charset, charcodes, unicode);
+//    ttime=GetTimer()-ttime;
+//    printf("render:   %7lf us\n",ttime);
+    if (err) return -1;
+//    fprintf(stderr, "fg: render t = %lf\n", GetTimer()-t);
+
+    desc->pic_a[pic_idx]->w = desc->pic_b[pic_idx]->w;
+    desc->pic_a[pic_idx]->h = desc->pic_b[pic_idx]->h;
+    desc->pic_a[pic_idx]->c = colors;
+
+    desc->pic_a[pic_idx]->bmp = NULL;
+
+//    fprintf(stderr, "fg: w = %d, h = %d\n", desc->pic_a[pic_idx]->w, desc->pic_a[pic_idx]->h);
+    return 0;
+    
+}
+
+int generate_tables(font_desc_t *desc, double thickness, double radius)
+{
+    int err;
+
+    int width = desc->max_height;
+    int height = desc->max_width;
+    
+    double A = log(1.0/base)/(radius*radius*2);
+    int mx, my, i;
+    unsigned volume2 = 0;		// volume under Gaussian area is exactly -pi*base/A
+    double volume_diff, volume_factor = 0;
+    unsigned char *omtp;
+    
+    desc->tables.g_r = ceil(radius);
+    desc->tables.o_r = ceil(thickness);
+    desc->tables.g_w = 2*desc->tables.g_r+1;
+    desc->tables.o_w = 2*desc->tables.o_r+1;
+    desc->tables.o_size = desc->tables.o_w * desc->tables.o_w;
+
+    desc->tables.g = (unsigned*)malloc(desc->tables.g_w * sizeof(unsigned));
+    desc->tables.gt = (unsigned*)malloc(256 * desc->tables.g_w * sizeof(unsigned));
+    desc->tables.gt2 = (unsigned*)malloc(256 * desc->tables.g_w * sizeof(unsigned));
+    desc->tables.om = (unsigned*)malloc(desc->tables.o_w*desc->tables.o_w * sizeof(unsigned));
+    desc->tables.omt = malloc(desc->tables.o_size*256);
+
+    omtp = desc->tables.omt;
+    desc->tables.tmp = malloc((width+1)*height*sizeof(short));
+    
+    if (desc->tables.g==NULL || desc->tables.gt==NULL || desc->tables.gt2==NULL
+	|| desc->tables.om==NULL || desc->tables.omt==NULL) {
+	return -1;
+    };
+
+    // gaussian curve with volume = 256
+    for (volume_diff=10000000; volume_diff>0.0000001; volume_diff*=0.5){
+	volume_factor+= volume_diff;
+	desc->tables.volume=0;
+	for (i = 0; i<desc->tables.g_w; ++i) {
+	    desc->tables.g[i] = (unsigned)(exp(A * (i-desc->tables.g_r)*(i-desc->tables.g_r)) * volume_factor + .5);
+	    desc->tables.volume+= desc->tables.g[i];
+	}
+	if(desc->tables.volume>256) volume_factor-= volume_diff;
+    }
+    desc->tables.volume=0;
+    for (i = 0; i<desc->tables.g_w; ++i) {
+	desc->tables.g[i] = (unsigned)(exp(A * (i-desc->tables.g_r)*(i-desc->tables.g_r)) * volume_factor + .5);
+	desc->tables.volume+= desc->tables.g[i];
+    }
+
+    // gauss table:
+    for(mx=0;mx<desc->tables.g_w;mx++){
+	for(i=0;i<256;i++){
+	    desc->tables.gt[256*mx+i] = (i*desc->tables.g[mx]*65536+(desc->tables.volume/2))/desc->tables.volume;
+	    desc->tables.gt2[mx+i*desc->tables.g_w] = i*desc->tables.g[mx];
+	}
+    }
+
+    /* outline matrix */
+    for (my = 0; my<desc->tables.o_w; ++my) {
+	for (mx = 0; mx<desc->tables.o_w; ++mx) {
+	    // antialiased circle would be perfect here, but this one is good enough
+	    double d = thickness + 1 - sqrt((mx-desc->tables.o_r)*(mx-desc->tables.o_r)+(my-desc->tables.o_r)*(my-desc->tables.o_r));
+	    desc->tables.om[mx+my*desc->tables.o_w] = d>=1 ? base : d<=0 ? 0 : (d*base + .5);
+	}
+    }
+
+    // outline table:
+    for(i=0;i<256;i++){
+	for(mx=0;mx<desc->tables.o_size;mx++) *(omtp++) = (i*desc->tables.om[mx] + (base/2))/base;
+    }
+
+    return 0;
+}
+
+
+/* decode from 'encoding' to unicode */
+static FT_ULong decode_char(iconv_t *cd, char c) {
+    FT_ULong o;
+    char *inbuf = &c;
+    char *outbuf = (char*)&o;
+    int inbytesleft = 1;
+    int outbytesleft = sizeof(FT_ULong);
+
+    size_t count = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+
+    /* convert unicode BigEndian -> MachineEndian */
+    o = be2me_32(o);
+
+    // if (count==-1) o = 0; // not OK, at least my iconv() returns E2BIG for all
+    if (outbytesleft!=0) o = 0;
+
+    /* we don't want control characters */
+    if (o>=0x7f && o<0xa0) o = 0;
+    return o;
+}
+
+static int prepare_charset(char *charmap, char *encoding, FT_ULong *charset, FT_ULong *charcodes) {
+    FT_ULong i;
+    int count = 0;
+    int charset_size;
+    iconv_t cd;
+    
+    // check if ucs-4 is available
+    cd = iconv_open(charmap, charmap);
+    if (cd==(iconv_t)-1) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "iconv doesn't know %s encoding. Use the source!\n", charmap);
+	return -1;
+    }
+    
+    iconv_close(cd);
+    
+    cd = iconv_open(charmap, encoding);
+    if (cd==(iconv_t)-1) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "Unsupported encoding `%s', use iconv --list to list character sets known on your system.\n", encoding);
+	return -1;
+    }
+    
+    charset_size = 256 - first_char;
+    for (i = 0; i<charset_size; ++i) {
+	charcodes[count] = i+first_char;
+	charset[count] = decode_char(&cd, i+first_char);
+	if (charset[count]!=0) ++count;
+    }
+    charcodes[count] = charset[count] = 0; ++count;
+    charset_size = count;
+
+    iconv_close(cd);
+    if (charset_size==0) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "No characters to render!\n");
+	return -1;
+    }
+    
+    return charset_size;
+}
+
+static int prepare_charset_unicode(FT_Face face, FT_ULong *charset, FT_ULong *charcodes) {
+    FT_ULong  charcode;
+    FT_UInt   gindex;
+    int i;
+
+    if (face->charmap==NULL || face->charmap->encoding!=ft_encoding_unicode) {
+	WARNING("Unicode charmap not available for this font. Very bad!");
+	return -1;
+    }
+
+    i = 0;
+    charcode = FT_Get_First_Char( face, &gindex );
+    while ( gindex != 0 ) {
+	if (charcode < 65536 && charcode >= 33) { // sanity check
+	    charset[i] = charcode;
+	    charcodes[i] = 0;
+	    i++;
+	}
+	charcode = FT_Get_Next_Char( face, charcode, &gindex );
+    }
+
+    mp_msg(MSGT_OSD, MSGL_V, "Unicode font: %d glyphs.\n", i);
+
+    return i;
+}
+
+static font_desc_t* init_font_desc()
+{
+    font_desc_t *desc;
+    int i;
+
+    desc = malloc(sizeof(font_desc_t));
+    if(!desc) return NULL;
+
+    /* setup sane defaults */
+    desc->name = NULL;
+    desc->fpath = NULL;
+
+    desc->face_cnt = 0;
+    desc->charspace = 0;
+    desc->spacewidth = 0;
+    desc->height = 0;
+    desc->max_width = 0;
+    desc->max_height = 0;
+
+    desc->tables.g = NULL;
+    desc->tables.gt = NULL;
+    desc->tables.gt2 = NULL;
+    desc->tables.om = NULL;
+    desc->tables.omt = NULL;
+    desc->tables.tmp = NULL;
+
+    for(i = 0; i < 65536; i++)
+	desc->start[i] = desc->width[i] = desc->font[i] = -1;
+    for(i = 0; i < 16; i++)
+	desc->pic_a[i] = desc->pic_b[i] = NULL;
+    
+    return desc;
+}
+
+void free_font_desc(font_desc_t *desc)
+{
+    int i;
+    
+    if (!desc) return;
+    
+    for(i = 0; i < 16; i++) {
+	if (desc->pic_a[i]) {
+	    if (desc->pic_a[i]->bmp) free(desc->pic_a[i]->bmp);
+	    if (desc->pic_a[i]->pal) free(desc->pic_a[i]->pal);
+	}
+	if (desc->pic_b[i]) {
+	    if (desc->pic_b[i]->bmp) free(desc->pic_b[i]->bmp);
+	    if (desc->pic_b[i]->pal) free(desc->pic_b[i]->pal);
+	}
+    }
+
+    if (desc->tables.g) free(desc->tables.g);
+    if (desc->tables.gt) free(desc->tables.gt);
+    if (desc->tables.gt2) free(desc->tables.gt2);
+    if (desc->tables.om) free(desc->tables.om);
+    if (desc->tables.omt) free(desc->tables.omt);
+    if (desc->tables.tmp) free(desc->tables.tmp);
+
+    for(i = 0; i < desc->face_cnt; i++) {
+	FT_Done_Face(desc->faces[i]);
+    }
+    
+}
+
+static int load_sub_face(char *name, FT_Face *face)
+{
+    int err;
+    
+    if (name) {
+	err = FT_New_Face(library, name, 0, face);
+    } else {
+	err = 1;
+    }
+     
+    if (err) {
+	err = FT_New_Face(library, get_path("subfont.ttf"), 0, face);
+	if (err) {
+	    err = FT_New_Face(library, DATADIR"/subfont.ttf", 0, face);
+	    if (err) {
+		mp_msg(MSGT_OSD, MSGL_ERR, "New_Face failed. Maybe the font path is wrong.\n");
+		mp_msg(MSGT_OSD, MSGL_ERR, "Please supply the text font file (~/.mplayer/subfont.ttf).\n");
+		return -1;
+	    }
+	}
+    }
+}
+
+static int load_osd_face(FT_Face *face)
+{
+    int err;
+
+    err = FT_New_Face(library, get_path("osd.pfb"), 0, face);
+    if (err) {
+	err = FT_New_Face(library, DATADIR"/osd.pfb", 0, face);
+	if (err) {
+	    mp_msg(MSGT_OSD, MSGL_ERR, "New_Face failed. Maybe the font path is wrong.\n");
+	    mp_msg(MSGT_OSD, MSGL_ERR, "Please supply the osd font file (~/.mplayer/osd.pfb).\n");
+	    return -1;
+	}
+    }
+}
+
+int kerning(font_desc_t *desc, int prevc, int c)
+{
+    FT_Vector kern;
+    
+    if (prevc < 0 || c < 0) return 0;
+    if (desc->font[prevc] != desc->font[c]) return 0;
+    FT_Get_Kerning(desc->faces[desc->font[c]], 
+		   desc->glyph_index[prevc], desc->glyph_index[c],
+		   ft_kerning_default, &kern);
+
+//    fprintf(stderr, "kern: %c %c %d\n", prevc, c, f266ToInt(kern.x));
+
+    return f266ToInt(kern.x);
+}
+
+font_desc_t* read_font_desc(char *fname, float factor, int movie_width, int movie_height)
+{
+    font_desc_t *desc;
+
+    FT_Face face;
+
+    FT_ULong my_charset[MAX_CHARSET_SIZE]; /* characters we want to render; Unicode */
+    FT_ULong my_charcodes[MAX_CHARSET_SIZE]; /* character codes in 'encoding' */
+
+    char *charmap = "ucs-4";
+    int err;
+    int charset_size;
+    int i, j;
+    int unicode;
+    
+    float movie_size;
+
+    float subtitle_font_ppem;
+    float osd_font_ppem;
+
+    switch (subtitle_autoscale) {
+    case 0:
+	movie_size = 100;
+	break;
+    case 1:
+	movie_size = movie_height;
+	break;
+    case 2:
+	movie_size = movie_width;
+	break;
+    case 3:
+	movie_size = sqrt(movie_height*movie_height+movie_width*movie_width);
+	break;
+    }
+
+    subtitle_font_ppem = movie_size*text_font_scale_factor/100.0;
+    osd_font_ppem = movie_size*osd_font_scale_factor/100.0;
+
+    if (subtitle_font_ppem < 5) subtitle_font_ppem = 5;
+    if (osd_font_ppem < 5) osd_font_ppem = 5;
+
+    if ((subtitle_font_encoding == NULL)
+	|| (strcasecmp(subtitle_font_encoding, "unicode") == 0)) {
+	unicode = 1;
+    } else {
+	unicode = 0;
+    }
+
+    desc = init_font_desc();
+    if(!desc) return NULL;
+
+//    t=GetTimer();
+
+    /* generate the subtitle font */
+    err = load_sub_face(fname, &face);
+    if (err) {
+	free_font_desc(desc);
+	return NULL;
+    }
+    desc->face_cnt++;
+    
+    if (unicode) {
+	charset_size = prepare_charset_unicode(face, my_charset, my_charcodes);
+    } else {
+	if (subtitle_font_encoding) {
+	    charset_size = prepare_charset(charmap, subtitle_font_encoding, my_charset, my_charcodes);
+	} else {
+	    charset_size = prepare_charset(charmap, "iso-8859-1", my_charset, my_charcodes);
+	}
+    }
+
+    if (charset_size < 0) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "prepare_charset failed.\n");
+	free_font_desc(desc);
+	return NULL;
+    }
+
+//    fprintf(stderr, "fg: prepare t = %lf\n", GetTimer()-t);
+
+    err = prepare_font(desc, face, subtitle_font_ppem, 0,
+		       charset_size, my_charset, my_charcodes, unicode,
+		       subtitle_font_thickness, subtitle_font_radius);
+
+    if (err) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "Cannot prepare font.\n");
+	free_font_desc(desc);
+	return NULL;
+    }
+
+    /* generate the OSD font */
+    err = load_osd_face(&face);
+    if (err) {
+	free_font_desc(desc);
+	return NULL;
+    }
+    desc->face_cnt++;
+    err = prepare_font(desc, face, osd_font_ppem, 1,
+		       OSD_CHARSET_SIZE, osd_charset, osd_charcodes, 0,
+		       subtitle_font_thickness, subtitle_font_radius);
+    
+    if (err) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "Cannot prepare font.\n");
+	free_font_desc(desc);
+	return NULL;
+    }
+
+    err = generate_tables(desc, subtitle_font_thickness, subtitle_font_radius);
+    
+    if (err) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "Cannot generate tables.\n");
+	free_font_desc(desc);
+	return NULL;
+    }
+
+    // final cleanup
+    j = '_';
+    render_one_glyph(desc, j);
+    if (desc->font[j] < 0) j = '?';
+    render_one_glyph(desc, j);
+    if (desc->font[j] >= 0) {
+	for(i = 0; i < 65536; i++) {
+	    if (desc->font[i] < 0) {
+		desc->start[i] = desc->start[j];
+		desc->width[i] = desc->width[j];
+		desc->font[i] = desc->font[j];
+	    }
+	}
+    }
+    desc->font[' ']=-1;
+    desc->width[' ']=desc->spacewidth;
+    return desc;
+}
+
+int init_freetype()
+{
+    int err;
+    
+    /* initialize freetype */
+    err = FT_Init_FreeType(&library);
+    if (err) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "Init_FreeType failed.\n");
+	return -1;
+    }
+    return 0;
+}
+
+int done_freetype()
+{
+    int err;
+    
+    err = FT_Done_FreeType(library);
+    if (err) {
+	mp_msg(MSGT_OSD, MSGL_ERR, "FT_Done_FreeType failed.\n");
+	return -1;
+    }
+
+    return 0;
+}
+
+#endif /* HAVE_FREETYPE */
diff -urN --exclude-from dontdiff vanilla/main/libvo/sub.c main/libvo/sub.c
--- vanilla/main/libvo/sub.c	Sat May 25 19:40:33 2002
+++ main/libvo/sub.c	Mon Aug 19 14:27:02 2002
@@ -40,16 +40,75 @@
     return h;
 }
 
+static void draw_alpha_buf(mp_osd_obj_t* obj, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)
+{
+    int dststride = obj->stride;
+    int dstskip = obj->stride-w;
+    int srcskip = stride-w;
+    int i, j;
+    unsigned char *b = obj->bitmap_buffer + (y0-obj->bbox.y1)*dststride + (x0-obj->bbox.x1);
+    unsigned char *a = obj->alpha_buffer + (y0-obj->bbox.y1)*dststride + (x0-obj->bbox.x1);
+    unsigned char *bs = src;
+    unsigned char *as = srca;
+
+    if (x0 < obj->bbox.x1 || x0+w > obj->bbox.x2 || y0 < obj->bbox.y1 || y0+h > obj->bbox.y2) {
+	fprintf(stderr, "osd text out of range!\n");
+	return;
+    }
+    
+    for (i = 0; i < h; i++) {
+	for (j = 0; j < w; j++, b++, a++, bs++, as++) {
+	    if (*b < *bs) *b = *bs;
+	    if (*as) {
+		if (*a == 0 || *a > *as) *a = *as;
+	    }
+	}
+	b+= dstskip;
+	a+= dstskip;
+	bs+= srcskip;
+	as+= srcskip;
+    }
+}
+
+static void alloc_buf(mp_osd_obj_t* obj)
+{
+    int len;
+    obj->stride = ((obj->bbox.x2-obj->bbox.x1)+7)&(~7);
+    len = obj->stride*(obj->bbox.y2-obj->bbox.y1);
+    if (obj->allocated<len) {
+	obj->allocated = len;
+	free(obj->bitmap_buffer);
+	free(obj->alpha_buffer);
+	obj->bitmap_buffer = (unsigned char *)memalign(16, len);
+	obj->alpha_buffer = (unsigned char *)memalign(16, len);
+    }
+    memset(obj->bitmap_buffer, 0, len);
+    memset(obj->alpha_buffer, 0, len);
+}
+
+inline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
+    if (obj->allocated > 0) {
+	draw_alpha(obj->bbox.x1,obj->bbox.y1,
+		   obj->bbox.x2-obj->bbox.x1,
+		   obj->bbox.y2-obj->bbox.y1,
+		   obj->bitmap_buffer,
+		   obj->alpha_buffer,
+		   obj->stride);
+    }
+}
+
 inline static void vo_update_text_osd(mp_osd_obj_t* obj,int dxs,int dys){
 	unsigned char *cp=vo_osd_text;
 	int x=20;
 	int h=0;
+	int font;
 
         obj->bbox.x1=obj->x=x;
         obj->bbox.y1=obj->y=10;
 
         while (*cp){
           int c=*cp++;
+	  render_one_glyph(vo_font, c);
           x+=vo_font->width[c]+vo_font->charspace;
 	  h=get_height(c,h);
         }
@@ -58,22 +117,19 @@
 	obj->bbox.y2=obj->bbox.y1+h;
 	obj->flags|=OSDFLAG_BBOX;
 
-}
-
-inline static void vo_draw_text_osd(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
-	unsigned char *cp=vo_osd_text;
-   	int font;
-        int x=obj->x;
+	alloc_buf(obj);
 
+	cp=vo_osd_text;
+	x = obj->x;
         while (*cp){
           int c=*cp++;
           if ((font=vo_font->font[c])>=0)
-            draw_alpha(x,obj->y,
-              vo_font->width[c],
-              vo_font->pic_a[font]->h,
-              vo_font->pic_b[font]->bmp+vo_font->start[c],
-              vo_font->pic_a[font]->bmp+vo_font->start[c],
-              vo_font->pic_a[font]->w);
+            draw_alpha_buf(obj,x,obj->y,
+			   vo_font->width[c],
+			   vo_font->pic_a[font]->h,
+			   vo_font->pic_b[font]->bmp+vo_font->start[c],
+			   vo_font->pic_a[font]->bmp+vo_font->start[c],
+			   vo_font->pic_a[font]->w);
           x+=vo_font->width[c]+vo_font->charspace;
         }
 }
@@ -89,39 +145,7 @@
 // 
 //  the above schema is rescalled to n=elems bars
 
-inline static void vo_update_text_progbar(mp_osd_obj_t* obj,int dxs,int dys){
-
-    obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
-    
-    if(vo_osd_progbar_type<0 || !vo_font){
-       obj->flags&=~OSDFLAG_VISIBLE;
-       return;
-    }
-    
-    {	int h=0;
-        int y=(dys-vo_font->height)/2;
-        int delimw=vo_font->width[OSD_PB_START]
-     		  +vo_font->width[OSD_PB_END]
-     		  +vo_font->charspace;
-        int width=(2*dxs-3*delimw)/3;
-   	int charw=vo_font->width[OSD_PB_0]+vo_font->charspace;
-        int elems=width/charw;
-   	int x=(dxs-elems*charw-delimw)/2;
-	h=get_height(OSD_PB_START,h);
-	h=get_height(OSD_PB_END,h);
-	h=get_height(OSD_PB_0,h);
-	h=get_height(OSD_PB_1,h);
-	obj->bbox.x1=obj->x=x;
-	obj->bbox.y1=obj->y=y;
-	obj->bbox.x2=x+width+delimw;
-	obj->bbox.y2=y+h; //vo_font->height;
-	obj->flags|=OSDFLAG_BBOX;
-	obj->params.progbar.elems=elems;
-    }
-    
-}
-
-inline static void vo_draw_text_progbar(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
+inline static void vo_draw_text_progbar_buf(mp_osd_obj_t* obj) {
    	unsigned char *s;
    	unsigned char *sa;
         int i,w,h,st,mark;
@@ -144,9 +168,10 @@
 //        printf("osd.progbar  width=%d  xpos=%d\n",width,x);
 
         c=vo_osd_progbar_type;
+	render_one_glyph(vo_font, c);
         if(vo_osd_progbar_type>0 && (font=vo_font->font[c])>=0) {
 	    int xp=x-vo_font->width[c]-vo_font->spacewidth;
-	   draw_alpha((xp<0?0:xp),y,
+	   draw_alpha_buf(obj,(xp<0?0:xp),y,
               vo_font->width[c],
               vo_font->pic_a[font]->h,
               vo_font->pic_b[font]->bmp+vo_font->start[c],
@@ -155,8 +180,9 @@
 	}
    
         c=OSD_PB_START;
+	render_one_glyph(vo_font, c);
         if ((font=vo_font->font[c])>=0)
-            draw_alpha(x,y,
+            draw_alpha_buf(obj,x,y,
               vo_font->width[c],
               vo_font->pic_a[font]->h,
               vo_font->pic_b[font]->bmp+vo_font->start[c],
@@ -165,6 +191,7 @@
         x+=vo_font->width[c]+vo_font->charspace;
 
    	c=OSD_PB_0;
+	render_one_glyph(vo_font, c);
    	if ((font=vo_font->font[c])>=0){
 	   w=vo_font->width[c];
 	   h=vo_font->pic_a[font]->h;
@@ -172,12 +199,13 @@
 	   sa=vo_font->pic_a[font]->bmp+vo_font->start[c];
 	   st=vo_font->pic_a[font]->w;
 	   if ((i=mark)) do {
-	       draw_alpha(x,y,w,h,s,sa,st);
+	       draw_alpha_buf(obj,x,y,w,h,s,sa,st);
 	       x+=charw;
 	   } while(--i);
 	}
 
    	c=OSD_PB_1;
+	render_one_glyph(vo_font, c);
 	if ((font=vo_font->font[c])>=0){
 	   w=vo_font->width[c];
 	   h=vo_font->pic_a[font]->h;
@@ -185,14 +213,15 @@
 	   sa=vo_font->pic_a[font]->bmp+vo_font->start[c];
 	   st=vo_font->pic_a[font]->w;
 	   if ((i=elems-mark)) do {
-	       draw_alpha(x,y,w,h,s,sa,st);
+	       draw_alpha_buf(obj,x,y,w,h,s,sa,st);
 	       x+=charw;
 	   } while(--i);
 	}
 
         c=OSD_PB_END;
+	render_one_glyph(vo_font, c);
         if ((font=vo_font->font[c])>=0)
-            draw_alpha(x,y,
+            draw_alpha_buf(obj,x,y,
               vo_font->width[c],
               vo_font->pic_a[font]->h,
               vo_font->pic_b[font]->bmp+vo_font->start[c],
@@ -205,13 +234,59 @@
 
 }
 
+inline static void vo_update_text_progbar(mp_osd_obj_t* obj,int dxs,int dys){
+
+    obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
+    
+    if(vo_osd_progbar_type<0 || !vo_font){
+       obj->flags&=~OSDFLAG_VISIBLE;
+       return;
+    }
+    
+    render_one_glyph(vo_font, OSD_PB_START);
+    render_one_glyph(vo_font, OSD_PB_END);
+    render_one_glyph(vo_font, OSD_PB_0);
+    render_one_glyph(vo_font, OSD_PB_1);
+    
+    {	int h=0;
+        int y=(dys-vo_font->height)/2;
+        int delimw=vo_font->width[OSD_PB_START]
+     		  +vo_font->width[OSD_PB_END]
+     		  +vo_font->charspace;
+        int width=(2*dxs-3*delimw)/3;
+   	int charw=vo_font->width[OSD_PB_0]+vo_font->charspace;
+        int elems=width/charw;
+   	int x=(dxs-elems*charw-delimw)/2;
+	int font, delta = 0;
+	if (vo_osd_progbar_type > 0 && (font=vo_font->font[vo_osd_progbar_type])>=0) {
+	    delta = vo_font->width[vo_osd_progbar_type]+vo_font->spacewidth;
+	    delta = (x-delta > 0) ? delta : x;
+	}
+	h=get_height(OSD_PB_START,h);
+	h=get_height(OSD_PB_END,h);
+	h=get_height(OSD_PB_0,h);
+	h=get_height(OSD_PB_1,h);
+	obj->bbox.x1=obj->x=x;
+	obj->bbox.y1=obj->y=y;
+	obj->bbox.x2=x+width+delimw;
+	obj->bbox.y2=y+h; //vo_font->height;
+	obj->flags|=OSDFLAG_BBOX;
+	obj->params.progbar.elems=elems;
+	obj->bbox.x1-=delta; // space for an icon
+    }
+
+    alloc_buf(obj);
+
+    vo_draw_text_progbar_buf(obj);
+}
+
 subtitle* vo_sub=NULL;
 
 // vo_draw_text_sub(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride))
 
 inline static void vo_update_text_sub(mp_osd_obj_t* obj,int dxs,int dys){
    unsigned char *t;
-   int c,i,j,l,x,y,font;
+   int c,i,j,l,x,y,font,prevc;
    int len;
    int k,lastk;
    int lastStripPosition;
@@ -244,6 +319,9 @@
 //	  printf("sub(%d) '%s'\n",len,t);
 //	  if(len<0) memy -=h; // according to max of vo_font->pic_a[font]->h 
 //	  else
+
+	  prevc = -1;
+
 	  for (j=0;j<=len;j++){
 	      if ((c=t[j])>=0x80){
 		 if (sub_utf8){
@@ -260,6 +338,7 @@
 		 mp_msg(MSGT_OSD,MSGL_WARN,"\nMAX_UCS exceeded!\n");
 	      }
 	      if (!c) c++; // avoid UCS 0
+	      render_one_glyph(vo_font, c);
 	      if (c==' '){
 		 lastk=k;
 		 lastStripPosition=j;
@@ -270,19 +349,22 @@
 		  }
 	      }
 	      obj->params.subtitle.utbl[k++]=c;
-	      xsize+=vo_font->width[c]+vo_font->charspace;
+	      xsize+=vo_font->width[c]+vo_font->charspace+kerning(vo_font,prevc,c);
 	      if (dxs<xsize){
+		  prevc = -1;
 		 if (lastStripPosition>0){
 		    j=lastStripPosition;
 		    xsize=lastxsize;
 		    k=lastk;
 		 } else {
-		    xsize -=vo_font->width[c]+vo_font->charspace; // go back
+		    xsize -=vo_font->width[c]+vo_font->charspace+kerning(vo_font,prevc,c);; // go back
 		    k--; // cut line here
 		    while (t[j] && t[j]!=' ') j++; // jump to the nearest space
 		 }
-	      } else if (j<len)
-		   continue;
+	      } else if (j<len) {
+		  prevc = c;
+		  continue;
+	      }
 	      if (h>obj->y){ // out of the screen so end parsing
 		 obj->y -= lasth - vo_font->height; // correct the y position
 		 l=0;
@@ -302,6 +384,7 @@
 	      }
 //	      printf("h: %d -> %d  \n",vo_font->height,h);
 	      obj->y -=h; // according to max of vo_font->pic_a[font]->h 
+	      prevc = -1;
 	  }
       }
 
@@ -317,6 +400,30 @@
     obj->bbox.y1=obj->y;
 //    obj->bbox.y2=obj->y+obj->params.subtitle.lines*vo_font->height;
     obj->flags|=OSDFLAG_BBOX;
+
+    alloc_buf(obj);
+
+    y = obj->y;
+    
+    i=j=0;
+    if ((l=obj->params.subtitle.lines)) for (;;) {
+ 	 x=obj->params.subtitle.xtbl[i++]; 
+	 prevc = -1;
+	 while ((c=obj->params.subtitle.utbl[j++])){
+	       x += kerning(vo_font,prevc,c);
+	       if ((font=vo_font->font[c])>=0)
+		  draw_alpha_buf(obj,x,y,
+			     vo_font->width[c],
+			     vo_font->pic_a[font]->h+y<obj->dys ? vo_font->pic_a[font]->h : obj->dys-y,
+			     vo_font->pic_b[font]->bmp+vo_font->start[c],
+			     vo_font->pic_a[font]->bmp+vo_font->start[c],
+			     vo_font->pic_a[font]->w);
+	       x+=vo_font->width[c]+vo_font->charspace;
+               prevc = c;
+	 }
+         if (!--l) break;
+         y+=vo_font->height;
+    }
     
 }
 
@@ -337,12 +444,13 @@
   spudec_draw_scaled(vo_spudec, obj->dxs, obj->dys, draw_alpha);
 }
 inline static void vo_draw_text_sub(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){
-   int i,j,c,x,l,font;
+   int i,j,c,x,l,font,prevc;
    int y=obj->y;
 
    i=j=0;
    if ((l=obj->params.subtitle.lines)) for (;;) {
  	 x=obj->params.subtitle.xtbl[i++]; 
+	 prevc = -1;
 	 while ((c=obj->params.subtitle.utbl[j++])){
 	       if ((font=vo_font->font[c])>=0)
 		  draw_alpha(x,y,
@@ -352,6 +460,7 @@
 			     vo_font->pic_a[font]->bmp+vo_font->start[c],
 			     vo_font->pic_a[font]->w);
 	          x+=vo_font->width[c]+vo_font->charspace;
+		  prevc = c;
 	 }
          if (!--l) break;
          y+=vo_font->height;
@@ -373,6 +482,9 @@
     osd->next=vo_osd_list;
     vo_osd_list=osd;
     osd->type=type;
+    osd->alpha_buffer = NULL;
+    osd->bitmap_buffer = NULL;
+    osd->allocated = -1;
     return osd;
 }
 
@@ -380,6 +492,8 @@
     mp_osd_obj_t* obj=vo_osd_list;
     while(obj){
 	mp_osd_obj_t* next=obj->next;
+	if (obj->alpha_buffer) free(obj->alpha_buffer);
+	if (obj->bitmap_buffer) free(obj->bitmap_buffer);
 	free(obj);
 	obj=next;
     }
@@ -494,13 +608,13 @@
 	    vo_draw_spudec_sub(obj, draw_alpha); // FIXME
 	    break;
 	case OSDTYPE_OSD:
-	    vo_draw_text_osd(obj,draw_alpha);
+	    vo_draw_text_from_buffer(obj,draw_alpha);
 	    break;
 	case OSDTYPE_SUBTITLE:
-	    vo_draw_text_sub(obj,draw_alpha);
+	    vo_draw_text_from_buffer(obj,draw_alpha);
 	    break;
 	case OSDTYPE_PROGBAR:
-	    vo_draw_text_progbar(obj,draw_alpha);
+	    vo_draw_text_from_buffer(obj,draw_alpha);
 	    break;
 	}
 	obj->old_bbox=obj->bbox;
diff -urN --exclude-from dontdiff vanilla/main/libvo/sub.h main/libvo/sub.h
--- vanilla/main/libvo/sub.h	Tue Jun  4 22:17:07 2002
+++ main/libvo/sub.h	Mon Aug 19 09:05:50 2002
@@ -40,6 +40,11 @@
 	    int elems;
 	} progbar;
     } params;
+    int stride;
+
+    int allocated;
+    unsigned char *alpha_buffer;
+    unsigned char *bitmap_buffer;
 } mp_osd_obj_t;
 
 
diff -urN --exclude-from dontdiff vanilla/main/mencoder.c main/mencoder.c
--- vanilla/main/mencoder.c	Thu Aug  8 18:06:26 2002
+++ main/mencoder.c	Sun Aug 18 19:47:57 2002
@@ -388,21 +388,6 @@
 
   mp_msg_set_level(verbose+MSGL_STATUS);
 
-// check font
-#ifdef USE_OSD
-  if(font_name){
-       vo_font=read_font_desc(font_name,font_factor,verbose>1);
-       if(!vo_font) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadFont,font_name);
-  } else {
-      // try default:
-       vo_font=read_font_desc(get_path("font/font.desc"),font_factor,verbose>1);
-       if(!vo_font)
-       vo_font=read_font_desc(DATADIR"/font/font.desc",font_factor,verbose>1);
-  }
-#endif
-
-  vo_init_osd();
-
   stream=open_stream(filename,vcd_track,&file_format);
 
   if(!stream){
@@ -475,6 +460,26 @@
     mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_NoVideoEncoderSelected);
     mencoder_exit(1,NULL);
   }
+
+// check font
+#ifdef USE_OSD
+#ifdef HAVE_FREETYPE
+  init_freetype();
+  vo_font=read_font_desc(font_name, font_factor, sh_video->disp_w, sh_video->disp_h);
+#else
+  if(font_name){
+       vo_font=read_font_desc(font_name,font_factor,verbose>1);
+       if(!vo_font) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadFont,font_name);
+  } else {
+      // try default:
+       vo_font=read_font_desc(get_path("font/font.desc"),font_factor,verbose>1);
+       if(!vo_font)
+       vo_font=read_font_desc(DATADIR"/font/font.desc",font_factor,verbose>1);
+  }
+#endif
+#endif
+
+  vo_init_osd();
 
 if(sh_audio && (out_audio_codec || seek_to_sec || !sh_audio->wf)){
   // Go through the codec.conf and find the best codec...
diff -urN --exclude-from dontdiff vanilla/main/mplayer.c main/mplayer.c
--- vanilla/main/mplayer.c	Mon Aug 12 18:20:31 2002
+++ main/mplayer.c	Sun Aug 18 19:47:03 2002
@@ -680,7 +680,7 @@
 
 //------ load global data first ------
 
-
+#ifndef HAVE_FREETYPE
 // check font
 #ifdef USE_OSD
   if(font_name){
@@ -693,8 +693,10 @@
        vo_font=read_font_desc(DATADIR"/font/font.desc",font_factor,verbose>1);
   }
 #endif
-
   vo_init_osd();
+#else
+  init_freetype();
+#endif
 
 #if defined(HAVE_LIRC) && ! defined(HAVE_NEW_INPUT)
   lirc_mp_setup();
@@ -1327,6 +1329,14 @@
     set_video_quality(sh_video,output_quality);
 }
 
+// ========== Load font ============
+#ifdef HAVE_FREETYPE
+#ifdef USE_OSD
+    vo_font=read_font_desc(font_name, font_factor, sh_video->disp_w, sh_video->disp_h);
+#endif
+    vo_init_osd();
+#endif
+
 // ========== Init display (sh_video->disp_w*sh_video->disp_h/out_fmt) ============
 
 current_module="init_vo";
@@ -3139,6 +3149,12 @@
 
 if(use_gui || playtree_iter != NULL){
 
+#ifdef HAVE_FREETYPE
+    current_module="uninit_font";
+    if (vo_font) free_font_desc(vo_font);
+    vo_font = NULL;
+#endif
+
   current_module="uninit_acodec";
   if(sh_audio) uninit_audio(sh_audio);
   sh_audio=NULL;
@@ -3169,6 +3185,10 @@
   eof = 0;
   goto play_next_file;
 }
+
+#ifdef HAVE_FREETYPE
+done_freetype();
+#endif
 
 exit_player(MSGTR_Exit_eof);
 


More information about the MPlayer-dev-eng mailing list