[MPlayer-dev-eng] [PATCH] freetype fixes
Jindrich Makovicka
makovick at KMLinux.fjfi.cvut.cz
Thu Aug 29 18:34:52 CEST 2002
Hi,
here is the fix for
- vo_aa sig11 because of vo_font hacks
- unicode should now work with ft2.0
- sig11 with -subfont-outline 0
- and some minor cleanups
Regards,
--
Jindrich Makovicka
-------------- next part --------------
diff -urN --exclude-from dontdiff vanilla/main/DOCS/mplayer.1 main/DOCS/mplayer.1
--- vanilla/main/DOCS/mplayer.1 Wed Aug 28 22:34:24 2002
+++ main/DOCS/mplayer.1 Wed Aug 28 23:38:49 2002
@@ -708,13 +708,9 @@
compiled in.
.TP
.B \-subfont-encoding
-Sets the font encoding.
-
-FreeType 2.1: When set to "unicode", all the glyphs from the
-font file will be rendered and unicode will be used. This is
-also the default setting.
-
-FreeType 2.0: Default is iso-8859-1. Unicode is not available.
+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 setting.
.TP
.B \-subfont-text-scale
Sets the subtitle text autoscale coefficient (percentage of the
diff -urN --exclude-from dontdiff vanilla/main/libvo/font_load.h main/libvo/font_load.h
--- vanilla/main/libvo/font_load.h Wed Aug 28 22:34:27 2002
+++ main/libvo/font_load.h Thu Aug 29 12:19:38 2002
@@ -16,6 +16,9 @@
} raw_file;
typedef struct {
+#ifdef HAVE_FREETYPE
+ int dynamic;
+#endif
char *name;
char *fpath;
int spacewidth;
@@ -47,7 +50,6 @@
unsigned volume;
unsigned *g;
- unsigned *gt;
unsigned *gt2;
unsigned *om;
unsigned char *omt;
@@ -76,7 +78,7 @@
int init_freetype();
int done_freetype();
-font_desc_t* read_font_desc(char* fname,float factor,int movie_width, int movie_height);
+font_desc_t* read_font_desc(char* fname,int movie_width, int movie_height);
void free_font_desc(font_desc_t *desc);
void render_one_glyph(font_desc_t *desc, int c);
@@ -89,16 +91,16 @@
raw_file* load_raw(char *name,int verbose);
font_desc_t* read_font_desc(char* fname,float factor,int verbose);
-static void inline render_one_glyph(font_desc_t *desc, int c)
+extern void inline render_one_glyph(font_desc_t *desc, int c)
{
}
-static int inline kerning(font_desc_t *desc, int prevc, int c)
+extern int inline kerning(font_desc_t *desc, int prevc, int c)
{
return 0;
}
-static void inline load_font(int width, int height)
+extern void inline load_font(int width, int height)
{
}
diff -urN --exclude-from dontdiff vanilla/main/libvo/font_load_ft.c main/libvo/font_load_ft.c
--- vanilla/main/libvo/font_load_ft.c Wed Aug 28 22:52:02 2002
+++ main/libvo/font_load_ft.c Thu Aug 29 12:20:40 2002
@@ -51,8 +51,8 @@
int force_load_font;
//// constants
-static int const colors = 256;
-static int const maxcolor = 255;
+static unsigned int const colors = 256;
+static unsigned int const maxcolor = 255;
static unsigned const base = 256;
static unsigned const first_char = 33;
#define MAX_CHARSET_SIZE 60000
@@ -111,11 +111,13 @@
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 space_advance = 20;
int width, height;
unsigned char *bbuffer;
int i, uni_charmap = 1;
+ error = FT_Select_Charmap(face, ft_encoding_unicode);
+// fprintf(stderr, "select unicode charmap: %d\n", error);
if (face->charmap==NULL || face->charmap->encoding!=ft_encoding_unicode) {
WARNING("Unicode charmap not available for this font. Very bad!");
@@ -188,12 +190,22 @@
width = ALIGN(width);
desc->pic_b[pic_idx]->charwidth = width;
+ if (width <= 0) {
+ mp_msg(MSGT_OSD, MSGL_ERR, "Wrong bounding box, width <= 0 !\n");
+ return -1;
+ }
+
if (ymax<=ymin) {
mp_msg(MSGT_OSD, MSGL_ERR, "Something went wrong. Use the source!\n");
return -1;
}
height = ymax - ymin + 2*padding;
+ if (height <= 0) {
+ mp_msg(MSGT_OSD, MSGL_ERR, "Wrong bounding box, height <= 0 !\n");
+ return -1;
+ }
+
if (desc->max_height < height) desc->max_height = height;
desc->pic_b[pic_idx]->charheight = height;
@@ -264,7 +276,7 @@
int height,
int stride) {
- int x, y, mx, my;
+ int x, y;
int skip = stride-width;
for (x = 0; x<width; ++x, ++s, ++t) *t = *s;
@@ -294,6 +306,20 @@
for (x = 0; x<width; ++x, ++s, ++t) *t = *s;
}
+// "0 pixel outline"
+void outline0(
+ unsigned char *s,
+ unsigned char *t,
+ int width,
+ int height,
+ int stride) {
+ int y;
+ for (y = 0; y<height; ++y) {
+ memcpy(t, s, width);
+ s += stride;
+ t += stride;
+ }
+}
// gaussian blur
void blur(
@@ -302,11 +328,9 @@
int width,
int height,
int stride,
- int *m,
int *m2,
int r,
- int mwidth,
- unsigned volume) {
+ int mwidth) {
int x, y;
@@ -345,7 +369,6 @@
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];
@@ -460,9 +483,7 @@
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;
@@ -474,6 +495,7 @@
// fprintf(stderr, "render_one_glyph %d\n", c);
+ if (!desc->dynamic) return;
if (desc->width[c] != -1) return;
if (desc->font[c] == -1) return;
@@ -482,7 +504,7 @@
// 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);
+ WARNING("FT_Load_Glyph 0x%02x (char 0x%04x) failed.", glyph_index, c);
desc->font[c] = -1;
return;
}
@@ -492,7 +514,7 @@
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);
+ WARNING("FT_Render_Glyph 0x%04x (char 0x%04x) failed.", glyph_index, c);
desc->font[c] = -1;
return;
}
@@ -501,7 +523,7 @@
// 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);
+ WARNING("FT_Get_Glyph 0x%04x (char 0x%04x) failed.", glyph_index, c);
desc->font[c] = -1;
return;
}
@@ -515,14 +537,14 @@
}
// allocate new memory, if needed
+// fprintf(stderr, "\n%d %d %d\n", desc->pic_b[font]->charwidth, desc->pic_b[font]->charheight, desc->pic_b[font]->current_alloc);
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;
-
- printf("\nincr=%d w=%d h=%d \n",increment,desc->pic_b[font]->charwidth,desc->pic_b[font]->charheight);
-
desc->pic_b[font]->current_alloc += ALLOC_INCR;
+// fprintf(stderr, "\nns = %d inc = %d\n", newsize, increment);
+
desc->pic_b[font]->bmp = realloc(desc->pic_b[font]->bmp, newsize);
desc->pic_a[font]->bmp = realloc(desc->pic_a[font]->bmp, newsize);
@@ -555,7 +577,9 @@
height = desc->pic_b[font]->charheight;
stride = desc->pic_b[font]->w;
- if (desc->tables.o_r <= 1) {
+ if (desc->tables.o_r == 0) {
+ outline0(bbuffer+off, abuffer+off, width, height, stride);
+ } else if (desc->tables.o_r == 1) {
outline1(bbuffer+off, abuffer+off, width, height, stride);
} else {
outline(bbuffer+off, abuffer+off, width, height, stride,
@@ -566,8 +590,8 @@
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);
+ desc->tables.gt2, desc->tables.g_r,
+ desc->tables.g_w);
// fprintf(stderr, "fg: blur t = %lf\n", GetTimer()-t);
}
@@ -624,14 +648,11 @@
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;
@@ -641,44 +662,50 @@
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));
+// fprintf(stderr, "o_r = %d\n", desc->tables.o_r);
+
+ if (desc->tables.g_r) {
+ desc->tables.g = (unsigned*)malloc(desc->tables.g_w * sizeof(unsigned));
+ desc->tables.gt2 = (unsigned*)malloc(256 * desc->tables.g_w * sizeof(unsigned));
+ if (desc->tables.g==NULL || desc->tables.gt2==NULL) {
+ return -1;
+ }
+ }
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) {
+ if (desc->tables.om==NULL || desc->tables.omt==NULL || desc->tables.tmp==NULL) {
return -1;
};
- // gaussian curve with volume = 256
- for (volume_diff=10000000; volume_diff>0.0000001; volume_diff*=0.5){
- volume_factor+= volume_diff;
+ if (desc->tables.g_r) {
+ // 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];
}
- 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];
+ // gauss table:
+ for(mx=0;mx<desc->tables.g_w;mx++){
+ for(i=0;i<256;i++){
+ 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) {
@@ -757,20 +784,19 @@
return charset_size;
}
-#ifdef HAVE_FREETYPE21
static int prepare_charset_unicode(FT_Face face, FT_ULong *charset, FT_ULong *charcodes) {
FT_ULong charcode;
FT_UInt gindex;
- int i;
+ int i,j;
if (face->charmap==NULL || face->charmap->encoding!=ft_encoding_unicode) {
WARNING("Unicode charmap not available for this font. Very bad!");
return -1;
}
-
+#ifdef HAVE_FREETYPE21
i = 0;
charcode = FT_Get_First_Char( face, &gindex );
- while ( gindex != 0 ) {
+ while (gindex != 0) {
if (charcode < 65536 && charcode >= 33) { // sanity check
charset[i] = charcode;
charcodes[i] = 0;
@@ -778,12 +804,22 @@
}
charcode = FT_Get_Next_Char( face, charcode, &gindex );
}
-
+#else
+ // for FT < 2.1 we have to use brute force enumeration
+ i = 0;
+ for (j = 33; j < 65536; j++) {
+ gindex = FT_Get_Char_Index(face, j);
+ if (gindex > 0) {
+ charset[i] = j;
+ charcodes[i] = 0;
+ i++;
+ }
+ }
+#endif
mp_msg(MSGT_OSD, MSGL_V, "Unicode font: %d glyphs.\n", i);
return i;
}
-#endif
static font_desc_t* init_font_desc()
{
@@ -794,6 +830,8 @@
if(!desc) return NULL;
memset(desc,0,sizeof(font_desc_t));
+ desc->dynamic = 1;
+
/* setup sane defaults */
desc->name = NULL;
desc->fpath = NULL;
@@ -806,7 +844,6 @@
desc->max_height = 0;
desc->tables.g = NULL;
- desc->tables.gt = NULL;
desc->tables.gt2 = NULL;
desc->tables.om = NULL;
desc->tables.omt = NULL;
@@ -841,7 +878,6 @@
}
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);
@@ -894,6 +930,7 @@
{
FT_Vector kern;
+ if (!vo_font->dynamic) return 0;
if (prevc < 0 || c < 0) return 0;
if (desc->font[prevc] != desc->font[c]) return 0;
if (desc->font[prevc] == -1 || desc->font[c] == -1) return 0;
@@ -906,7 +943,7 @@
return f266ToInt(kern.x);
}
-font_desc_t* read_font_desc(char *fname, float factor, int movie_width, int movie_height)
+font_desc_t* read_font_desc(char *fname, int movie_width, int movie_height)
{
font_desc_t *desc;
@@ -927,9 +964,6 @@
float osd_font_ppem;
switch (subtitle_autoscale) {
- case 0:
- movie_size = 100;
- break;
case 1:
movie_size = movie_height;
break;
@@ -939,6 +973,9 @@
case 3:
movie_size = sqrt(movie_height*movie_height+movie_width*movie_width);
break;
+ default:
+ movie_size = 100;
+ break;
}
subtitle_font_ppem = movie_size*text_font_scale_factor/100.0;
@@ -947,16 +984,15 @@
if (subtitle_font_ppem < 5) subtitle_font_ppem = 5;
if (osd_font_ppem < 5) osd_font_ppem = 5;
-#ifdef HAVE_FREETYPE21
+ if (subtitle_font_ppem > 128) subtitle_font_ppem = 128;
+ if (osd_font_ppem > 128) osd_font_ppem = 128;
+
if ((subtitle_font_encoding == NULL)
|| (strcasecmp(subtitle_font_encoding, "unicode") == 0)) {
unicode = 1;
} else {
unicode = 0;
}
-#else
- unicode = 0;
-#endif
desc = init_font_desc();
if(!desc) return NULL;
@@ -969,8 +1005,8 @@
mp_msg(MSGT_OSD, MSGL_ERR, "subtitle font: load_sub_face failed.\n");
goto gen_osd;
}
+ desc->face_cnt++;
-#ifdef HAVE_FREETYPE21
if (unicode) {
charset_size = prepare_charset_unicode(face, my_charset, my_charcodes);
} else {
@@ -980,13 +1016,6 @@
charset_size = prepare_charset(charmap, "iso-8859-1", 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);
- }
-#endif
if (charset_size < 0) {
mp_msg(MSGT_OSD, MSGL_ERR, "subtitle font: prepare_charset failed.\n");
@@ -996,7 +1025,7 @@
// fprintf(stderr, "fg: prepare t = %lf\n", GetTimer()-t);
- err = prepare_font(desc, face, subtitle_font_ppem, desc->face_cnt,
+ err = prepare_font(desc, face, subtitle_font_ppem, desc->face_cnt-1,
charset_size, my_charset, my_charcodes, unicode,
subtitle_font_thickness, subtitle_font_radius);
@@ -1005,7 +1034,6 @@
free_font_desc(desc);
return NULL;
}
- desc->face_cnt++;
gen_osd:
@@ -1015,7 +1043,9 @@
free_font_desc(desc);
return NULL;
}
- err = prepare_font(desc, face, osd_font_ppem, desc->face_cnt,
+ desc->face_cnt++;
+
+ err = prepare_font(desc, face, osd_font_ppem, desc->face_cnt-1,
OSD_CHARSET_SIZE, osd_charset, osd_charcodes, 0,
subtitle_font_thickness, subtitle_font_radius);
@@ -1024,7 +1054,6 @@
free_font_desc(desc);
return NULL;
}
- desc->face_cnt++;
err = generate_tables(desc, subtitle_font_thickness, subtitle_font_radius);
@@ -1084,10 +1113,13 @@
vo_image_width = width;
vo_image_height = height;
+ // protection against vo_aa font hacks
+ if (vo_font && !vo_font->dynamic) return;
+
if (vo_font) free_font_desc(vo_font);
#ifdef USE_OSD
- vo_font=read_font_desc(font_name, font_factor, width, height);
+ vo_font=read_font_desc(font_name, width, height);
#endif
}
diff -urN --exclude-from dontdiff vanilla/main/libvo/vo_aa.c main/libvo/vo_aa.c
--- vanilla/main/libvo/vo_aa.c Fri Jul 26 18:21:03 2002
+++ main/libvo/vo_aa.c Thu Aug 29 12:21:29 2002
@@ -256,6 +256,10 @@
vo_font->pic_a[0]=malloc(sizeof(raw_file));
vo_font->pic_b[0]=malloc(sizeof(raw_file));
+#ifdef HAVE_FREETYPE
+ vo_font->dynamic = 0;
+#endif
+
vo_font->spacewidth=1;
vo_font->charspace=0;
vo_font->height=1;
@@ -530,10 +534,15 @@
#ifdef USE_OSD
static void draw_alpha(int x,int y, int w,int h, unsigned char* src, unsigned char *srca, int stride){
-
- c->textbuffer[x + y*aa_scrwidth(c)] = src[0];
- c->attrbuffer[x + y*aa_scrwidth(c)] = aaopt_subcolor;
-
+ int i,j;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ if (src[i*stride+j] > 0) {
+ c->textbuffer[x + j + (y+i)*aa_scrwidth(c)] = src[i*stride+j];
+ c->attrbuffer[x + j + (y+i)*aa_scrwidth(c)] = aaopt_subcolor;
+ }
+ }
+ }
}
static void clear_alpha(int x0,int y0, int w,int h) {
More information about the MPlayer-dev-eng
mailing list