diff --exclude-from dontdiff -urN 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 Wed Aug 14 11:16:38 2002 @@ -613,6 +613,42 @@ .I EXAMPLE: \-font ~/.mplayer/arial\-14/font.desc + +.I NOTE: + With FreeType, this options 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-radius +Sets the font blur radius. +.TP +.B \-subfont-thickness +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 --exclude-from dontdiff -urN 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 --exclude-from dontdiff -urN 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 Wed Aug 14 18:16:40 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-radius", &subtitle_font_radius, CONF_TYPE_FLOAT, CONF_RANGE, 0, 20, NULL}, + {"subfont-thickness", &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 --exclude-from dontdiff -urN 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 @@ -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 --exclude-from dontdiff -urN 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 --exclude-from dontdiff -urN 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 #include @@ -6,7 +9,6 @@ #include #include -#include "config.h" #include "font_load.h" extern char *get_path ( char * ); @@ -300,3 +302,5 @@ } #endif + +#endif /* HAVE_FREETYPE */ diff --exclude-from dontdiff -urN 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 Wed Aug 14 11:58:41 2002 @@ -1,3 +1,4 @@ +#include "config.h" typedef struct { unsigned char *bmp; @@ -22,5 +23,21 @@ 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; + +font_desc_t* read_font_desc(float factor,int movie_width, int movie_height); +void free_font_desc(font_desc_t *desc); + +#else + raw_file* load_raw(char *name,int verbose); font_desc_t* read_font_desc(char* fname,float factor,int verbose); + +#endif diff --exclude-from dontdiff -urN 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 Wed Aug 14 18:58:04 2002 @@ -0,0 +1,817 @@ +/* + * Renders antialiased fonts for mplayer using freetype library. + * Should work with TrueType, Type1 and any other font supported by libfreetype. + * + * Artur Zaprzala + * + * ported inside mplayer by Jindrich Makovicka + * + * + */ + +#include "config.h" + +#ifdef HAVE_FREETYPE + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 = 8.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) + +static double t; + + +static void paste_bitmap(unsigned char *bbuffer, FT_Bitmap *bitmap, int x, int y, int width) { + 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; --h, drow+=width, srow+=bitmap->pitch) + for (w = bitmap->width, 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; --h, drow+=width, srow+=bitmap->pitch) + for (w = bitmap->width, sp=dp=0; w>0; --w, ++dp, ++sp) + bbuffer[drow+dp] = bitmap->buffer[srow+sp]; +} + +static int render(font_desc_t *desc, FT_Face face, float ppem, int padding, int pic_idx, + int charset_size, FT_ULong *charset, FT_ULong *charcodes, int unicode) { + FT_Error error; + FT_Glyph *glyphs; + FT_BitmapGlyph glyph; + int const load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + int pen_x = 0, pen_xa; + int ymin = INT_MAX, ymax = INT_MIN; + int i, uni_charmap = 1; + int baseline, space_advance = 20; + int glyphs_count = 0; + int width, height; + unsigned char *bbuffer; + + 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, floatTof266(ppem), 0, 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; inum_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); + + // render glyphs, compute bitmap size and [characters] section + glyphs = (FT_Glyph*)malloc(charset_size*sizeof(FT_Glyph*)); + for (i= 0; i255 ? '.':code); + continue; + } + } + + // load glyph + error = FT_Load_Glyph(face, glyph_index, load_flags); + if (error) { + WARNING("FT_Load_Glyph 0x%02x (char 0x%02x|U+%04X) failed.", glyph_index, code, character); + continue; + } + slot = face->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); + continue; + } + } + + // 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); + continue; + } + glyphs[glyphs_count++] = (FT_Glyph)glyph; + + // max height + if (glyph->top > ymax) { + ymax = glyph->top; + //eprintf("%3i: ymax %i (%c)\n", code, ymax, code); + } + if (glyph->top - glyph->bitmap.rows < ymin) { + ymin = glyph->top - glyph->bitmap.rows; + //eprintf("%3i: ymin %i (%c)\n", code, ymin, code); + } + + /* advance pen */ + pen_xa = pen_x + f266ToInt(slot->advance.x) + 2*padding; + + desc->start[unicode?character:code] = pen_x; + desc->width[unicode?character:code] = pen_xa-pen_x; + desc->font[unicode?character:code] = pic_idx; + + pen_x = ALIGN(pen_xa); + } + + width = pen_x; + pen_x = 0; + + if (ymax<=ymin) { + mp_msg(MSGT_OSD, MSGL_ERR, "Something went wrong. Use the source!\n"); + return -1; + } + + height = ymax - ymin + 2*padding; + baseline = ymax + padding; + + // end of font.desc + mp_msg(MSGT_OSD, MSGL_DBG2, "bitmap size: %ix%i\n", width, height); + + + bbuffer = (unsigned char*)malloc(width*height); + if (bbuffer==NULL) { + mp_msg(MSGT_OSD, MSGL_ERR, "malloc failed.\n"); + return -1; + } + + memset(bbuffer, 0, width*height); + 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; + + /* paste glyphs */ + for (i= 0; ibitmap, + pen_x + padding + glyph->left, + baseline - glyph->top, + width); + + /* advance pen */ + pen_x += f1616ToInt(glyph->root.advance.x) + 2*padding; + pen_x = ALIGN(pen_x); + + FT_Done_Glyph((FT_Glyph)glyph); + } + free(glyphs); + + return 0; +} + +// general outline +void outline( + unsigned char *src, + unsigned char *dest, + unsigned short *tmp, + int width, + int height, + unsigned char *m, + int r, + int mwidth) { + + int size = width*height; + int i, j, x; + + unsigned char *s; + unsigned short *t; + + memset(tmp, 0, size*sizeof(unsigned short)); + + for (i = -r; i <= r; i++) { + for (j = -r; j <= r; j++,m++) { + int x1,x2,shift; + unsigned v; + shift = i*width+j; + if (shift <= 0) { + x1 = -shift; + x2 = size; + } else { + x1 = 0; + x2 = size-shift; + } + t = tmp + x1; + s = src + x1 + shift; + for (x = x1; x < x2; x++,s++,t++) { + v = *s * *m; + if (*t < v) *t = v; + } + } + } + + s = dest; + t = tmp; + for (x = 0; x < width*height; x++,s++,t++) { + *s = (*t + 64) / 128; + } + +} + +// gaussian blur +void blur( + unsigned char *buffer, + unsigned short *tmp, + int width, + int height, + unsigned char *m, + int r, + int mwidth, + unsigned volume) { + + int size = width*height; + int i, j, x; + + unsigned char *s; + unsigned short *t; + unsigned char *p; + + /* horizontal blur */ + memset(tmp, 0, size*sizeof(unsigned short)); + p = m; + for (j = -r; j <= r; j++,p++) { + int x1,x2,shift; + shift = j; + if (shift <= 0) { + x1 = -shift; + x2 = size; + } else { + x1 = 0; + x2 = size-shift; + } + t = tmp + x1; + s = buffer + x1 + shift; + for (x = x1; x < x2; x++,s++,t++) { + *t += (unsigned short)*s * *p; + } + } + + s = buffer; + t = tmp; + for (x = 0; x < width*height; x++,s++,t++) { + *s = *t / volume; + } + + /* vertical blur */ + memset(tmp, 0, size*sizeof(unsigned short)); + p = m; + for (i = -r; i <= r; i++,p++) { + int x1,x2,shift; + shift = i*width; + if (shift <= 0) { + x1 = -shift; + x2 = size; + } else { + x1 = 0; + x2 = size-shift; + } + t = tmp + x1; + s = buffer + x1 + shift; + for (x = x1; x < x2; x++,s++,t++) { + *t += (unsigned short)*s * *p; + } + } + + s = buffer; + t = tmp; + for (x = 0; x < width*height; x++,s++,t++) { + *s = *t / volume; + } + +} + + +// 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=1 ? 128 : d<=0 ? 0 : (d*128 + .5); + } + } + + outline(bbuffer, abuffer, tmp, width, height, om, o_r, o_w); +// fprintf(stderr, "fg: outline t = %lf\n", GetTimer()-t); + + blur(abuffer, tmp, width, height, g, g_r, g_w, volume2); +// fprintf(stderr, "fg: blur t = %lf\n", GetTimer()-t); + + free(tmp); + free(g); + free(om); +} + +static void resample_alpha(font_desc_t *desc, int pic_idx, float factor) +{ + int f=factor*256.0f; + int size=desc->pic_a[pic_idx]->w*desc->pic_a[pic_idx]->h; + int j; + for(j=0;jpic_a[pic_idx]->bmp[j]; // alpha + int y=desc->pic_b[pic_idx]->bmp[j]; // 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; + desc->pic_a[pic_idx]->bmp[j]=x; + } + if(!desc->height) desc->height=desc->pic_a[pic_idx]->h; +} + + +static int generate_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->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; + + err = render(desc, face, ppem, padding, pic_idx, charset_size, charset, charcodes, unicode); + 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 = (unsigned char*)malloc(desc->pic_a[pic_idx]->w*desc->pic_a[pic_idx]->h); + memset(desc->pic_a[pic_idx]->bmp, 0, desc->pic_a[pic_idx]->w*desc->pic_a[pic_idx]->h); + if (!desc->pic_a[pic_idx]->bmp) return -1; + +// fprintf(stderr, "fg: w = %d, h = %d\n", desc->pic_a[pic_idx]->w, desc->pic_a[pic_idx]->h); + + + alpha(desc->pic_a[pic_idx]->bmp, desc->pic_b[pic_idx]->bmp, + desc->pic_b[pic_idx]->w, desc->pic_b[pic_idx]->h, + thickness, radius); + +// fprintf(stderr, "fg: alpha t = %lf\n", GetTimer()-t); + + 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; icharmap==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 ) { + 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->charspace = 0; + desc->spacewidth = 0; + desc->height = 0; + for(i = 0; i < 512; 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); + } + } + +} + +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; + } + } +} + +font_desc_t* read_font_desc(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(); + + /* initialize freetype */ + err = FT_Init_FreeType(&library); + if (err) { + mp_msg(MSGT_OSD, MSGL_ERR, "Init_FreeType failed.\n"); + return NULL; + } + + /* generate the subtitle font */ + err = load_sub_face(font_name, &face); + if (err) { + free_font_desc(desc); + return NULL; + } + + 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 = generate_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 generate 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; + } + err = generate_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 generate font.\n"); + free_font_desc(desc); + return NULL; + } + + err = FT_Done_FreeType(library); + if (err) { + mp_msg(MSGT_OSD, MSGL_ERR, "FT_Done_FreeType failed.\n"); + free_font_desc(desc); + return NULL; + } + + resample_alpha(desc, 0, factor); + resample_alpha(desc, 1, factor); + + // final cleanup + j = '_'; + if (desc->font[j] < 0) j = '?'; + for(i = 0; i < 512; 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; +} + +#endif /* HAVE_FREETYPE */ diff --exclude-from dontdiff -urN vanilla/main/mencoder.c main/mencoder.c --- vanilla/main/mencoder.c Thu Aug 8 18:06:26 2002 +++ main/mencoder.c Wed Aug 14 09:16:09 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,25 @@ mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_NoVideoEncoderSelected); mencoder_exit(1,NULL); } + +// check font +#ifdef USE_OSD +#ifdef HAVE_FREETYPE + vo_font=read_font_desc(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 --exclude-from dontdiff -urN vanilla/main/mplayer.c main/mplayer.c --- vanilla/main/mplayer.c Mon Aug 12 18:20:31 2002 +++ main/mplayer.c Wed Aug 14 12:23:01 2002 @@ -680,7 +680,7 @@ //------ load global data first ------ - +#ifndef HAVE_FREETYPE // check font #ifdef USE_OSD if(font_name){ @@ -693,8 +693,8 @@ vo_font=read_font_desc(DATADIR"/font/font.desc",font_factor,verbose>1); } #endif - vo_init_osd(); +#endif #if defined(HAVE_LIRC) && ! defined(HAVE_NEW_INPUT) lirc_mp_setup(); @@ -1327,6 +1327,14 @@ set_video_quality(sh_video,output_quality); } +// ========== Load font ============ +#ifdef HAVE_FREETYPE +#ifdef USE_OSD + vo_font=read_font_desc(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"; @@ -3138,6 +3146,12 @@ #endif 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);