[MPlayer-dev-eng] [PATCH] Remove font attributes from subtitles

Salvatore Falco sfalco at studenti.ing.uniroma1.it
Wed Sep 21 11:04:42 CEST 2005


On Mon, Sep 19, 2005 at 07:57:01PM -0400, Ergzay wrote:
> I'm new to this list so I only saw this message by this reply. I would 
> LOVE to have full subtitle rendering including support of the formats 
> in ASS/SSA subtitles.

Some time ago, around March, I coded an initial support for SSA styles.
I also added management of multiple fonts and "advanced" positioning.

I am attaching the patch vs. CVS of March.

I have no time to keep on developing the code, I hope someone else would.

Just a side note. My code loads the fonts the first time they are needed;
this means that if many fonts are loaded at the same time, the delay is
visible as a brief but noticeable stop in video playing. I would have
introduced an initial caching of all the fonts to remove this nuissance.

Best regards,
    Salvatore Falco
    
-------------- next part --------------
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/AUTHORS MPlayer-20050307.patch/AUTHORS
--- MPlayer-20050307/AUTHORS	2005-03-29 23:31:46.906547104 +0200
+++ MPlayer-20050307.patch/AUTHORS	2005-03-09 15:51:34.000000000 +0100
@@ -220,6 +220,8 @@
     * jacosub parsing & dump support
     * overlapping subtitles & sub sorting support
     * SAMI subtitles dump support
+    * subtitle alignment: handling code + SAMI, SSA & JACOsub
+    * subtitle styles: initial support + SSA
 
 Feigl, Johannes (jaf) <johannes.feigl at aon.at>
     * original German docs translation (outdated)
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/cfg-common.h MPlayer-20050307.patch/cfg-common.h
--- MPlayer-20050307/cfg-common.h	2005-02-24 16:00:47.000000000 +0100
+++ MPlayer-20050307.patch/cfg-common.h	2005-03-09 22:59:52.000000000 +0100
@@ -264,11 +264,11 @@
 	{"spugauss", &spu_gaussvar, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 3.0, 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-text-scale", &text_font_scale_factor, CONF_TYPE_FLOAT, CONF_RANGE, 0, 200, 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},
+ 	{"subfont-autoscale", &subtitle_autoscale, CONF_TYPE_INT, CONF_RANGE, 0, 4, NULL},
 #endif
 #ifdef HAVE_FONTCONFIG
 	{"fontconfig", &font_fontconfig, CONF_TYPE_FLAG, 0, 0, 1, NULL},
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/DOCS/man/en/mplayer.1 MPlayer-20050307.patch/DOCS/man/en/mplayer.1
--- MPlayer-20050307/DOCS/man/en/mplayer.1	2005-03-06 22:22:08.000000000 +0100
+++ MPlayer-20050307.patch/DOCS/man/en/mplayer.1	2005-03-10 14:36:09.000000000 +0100
@@ -1611,24 +1611,22 @@
 Same as \-audiofile, but for subtitle streams (OggDS?).
 .
 .TP
-.B \-subfont-autoscale <0\-3> (FreeType only)
+.B \-subfont-autoscale <0\-4> (FreeType only)
 Sets the autoscale mode.
-.br
-.I NOTE:
-0 means that text scale and OSD scale are font heights in points.
-.sp 1
 The mode can be:
 .sp 1
 .PD 0
 .RSs
 .IPs 0
-no autoscale
+no autoscale, text scale and OSD scale are font heights in points.
 .IPs 1
 proportional to movie height
 .IPs 2
 proportional to movie width
 .IPs 3
 proportional to movie diagonal (default)
+.IPs 4
+no autoscale, and text scale is percentage of default size
 .RE
 .PD 1
 .
@@ -1651,8 +1649,8 @@
 Sets the font outline thickness (default: 2).
 .
 .TP
-.B \-subfont-text-scale <0\-100> (FreeType only)
-Sets the subtitle text autoscale coefficient as percentage of the
+.B \-subfont-text-scale <0\-200> (FreeType only)
+Sets the subtitle text autoscale coefficient: as percentage of the
 screen size (default: 5).
 .
 .TP
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/libmpdemux/demux_ogg.c MPlayer-20050307.patch/libmpdemux/demux_ogg.c
--- MPlayer-20050307/libmpdemux/demux_ogg.c	2005-02-27 19:11:16.000000000 +0100
+++ MPlayer-20050307.patch/libmpdemux/demux_ogg.c	2005-03-09 15:51:34.000000000 +0100
@@ -161,7 +161,6 @@
 
 #include "../subreader.h"
 #include "../libvo/sub.h"
-#define OGG_SUB_MAX_LINE 128
 
 static subtitle ogg_sub;
 extern subtitle* vo_sub;
@@ -222,7 +221,7 @@
   int lcv;
   if(!ogg_sub.text[0]) // not yet allocated
   for (lcv = 0; lcv < SUB_MAX_TEXT; lcv++) {
-    ogg_sub.text[lcv] = (char*)malloc(OGG_SUB_MAX_LINE);
+    ogg_sub.text[lcv] = (char*)malloc(SUB_LINE_LENGTH);
   }
 }
 
@@ -258,7 +257,7 @@
     }
     while (1) {
       int c = packet[lcv++];
-      if(c=='\n' || c==0 || line_pos >= OGG_SUB_MAX_LINE-1){
+      if(c=='\n' || c==0 || line_pos >= SUB_LINE_LENGTH - 1){
 	  ogg_sub.text[ogg_sub.lines][line_pos] = 0; // close sub
           if(line_pos) ogg_sub.lines++;
 	  if(!c || ogg_sub.lines>=SUB_MAX_TEXT) break; // EOL or TooMany
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/libvo/font_load_ft.c MPlayer-20050307.patch/libvo/font_load_ft.c
--- MPlayer-20050307/libvo/font_load_ft.c	2004-10-28 03:15:52.000000000 +0200
+++ MPlayer-20050307.patch/libvo/font_load_ft.c	2005-03-09 23:01:19.000000000 +0100
@@ -951,7 +951,8 @@
     return f266ToInt(kern.x);
 }
 
-font_desc_t* read_font_desc_ft(char *fname, int movie_width, int movie_height)
+// font_point_size: if > 0, is the font dimension in points, otherwise means "use subtitle_autoscale"
+font_desc_t* read_font_desc_ft(char *fname, int movie_width, int movie_height, int font_point_size)
 {
     font_desc_t *desc;
 
@@ -986,7 +987,10 @@
 	break;
     }
 
-    subtitle_font_ppem = movie_size*text_font_scale_factor/100.0;
+    if (font_point_size > 0)
+	subtitle_font_ppem = font_point_size;
+    else
+	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;
@@ -1120,21 +1124,24 @@
     return 0;
 }
 
-void load_font_ft(int width, int height) 
+#ifdef HAVE_FONTCONFIG
+font_desc_list_t *font_desc_list_p = NULL;
+#endif
+
+void load_font_ft(int width, int height, char* font_name, int font_point_size)
 {
 #ifdef HAVE_FONTCONFIG
     FcPattern *fc_pattern;
     FcChar8 *s;
     FcBool scalable;
 #endif
+    int displayed_point_size = (int)((subtitle_autoscale == 4) ? font_point_size * text_font_scale_factor / 100.0 : font_point_size);
     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
 #ifdef HAVE_FONTCONFIG
     if (font_fontconfig)
@@ -1155,12 +1162,34 @@
 	}
 	// s doesn't need to be freed according to fontconfig docs
 	FcPatternGetString(fc_pattern, FC_FILE, 0, &s);
-	vo_font=read_font_desc_ft(s, width, height);
+	if (font_desc_list_p == NULL) {
+	    vo_font = read_font_desc_ft(s, width, height, displayed_point_size);
+	    font_desc_list_p = (font_desc_list_t *)malloc(sizeof(font_desc_list_t));
+	    font_desc_list_p->font_name = strdup(font_name);
+	    font_desc_list_p->vo_font = vo_font;
+	    font_desc_list_p->next = NULL;
+	} else {
+	    font_desc_list_t *fdlp;
+	    for (fdlp = font_desc_list_p ; (strcmp(fdlp->font_name, font_name) != 0) && (fdlp->next != NULL) ; fdlp = fdlp->next);
+	    if (strcmp(fdlp->font_name, font_name) == 0) {
+		vo_font = fdlp->vo_font;
+	    } else {
+		vo_font = read_font_desc_ft(s, width, height, displayed_point_size);
+		fdlp = font_desc_list_p;
+		font_desc_list_p = (font_desc_list_t *)malloc(sizeof(font_desc_list_t));
+		font_desc_list_p->font_name = strdup(font_name);
+		font_desc_list_p->vo_font = vo_font;
+		font_desc_list_p->next = fdlp;
+	    }
+	}
 	free(fc_pattern);
     }
     else
 #endif
-    vo_font=read_font_desc_ft(font_name, width, height);
+{
+    if (vo_font) free_font_desc(vo_font);
+    vo_font=read_font_desc_ft(font_name, width, height, displayed_point_size);
+}
 #endif
 }
 
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/libvo/font_load.h MPlayer-20050307.patch/libvo/font_load.h
--- MPlayer-20050307/libvo/font_load.h	2003-11-20 17:25:40.000000000 +0100
+++ MPlayer-20050307.patch/libvo/font_load.h	2005-03-09 15:51:34.000000000 +0100
@@ -65,6 +65,14 @@
 
 #ifdef HAVE_FREETYPE
 
+typedef struct font_desc_list font_desc_list_t;
+struct font_desc_list {
+    char *font_name;
+//    int font_point_size; // not necessary: font_name contains the number of points
+    font_desc_t *vo_font;
+    font_desc_list_t * next;
+} font_desc_list;
+
 extern char *subtitle_font_encoding;
 extern float text_font_scale_factor;
 extern float osd_font_scale_factor;
@@ -80,13 +88,13 @@
 int init_freetype();
 int done_freetype();
 
-font_desc_t* read_font_desc_ft(char* fname,int movie_width, int movie_height);
+font_desc_t* read_font_desc_ft(char* fname,int movie_width, int movie_height, int font_point_size);
 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);
 
-void load_font_ft(int width, int height);
+void load_font_ft(int width, int height, char *font_name, int font_point_size);
 
 #else
 
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/libvo/sub.c MPlayer-20050307.patch/libvo/sub.c
--- MPlayer-20050307/libvo/sub.c	2004-10-28 03:15:52.000000000 +0200
+++ MPlayer-20050307.patch/libvo/sub.c	2005-03-09 15:51:34.000000000 +0100
@@ -88,7 +88,7 @@
     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: bbox [%d %d %d %d], txt [%d %d %d %d]\n",
+	mp_msg(MSGT_SUBREADER,MSGL_ERR,"OSD: osd text out of range: bbox [%d %d %d %d], txt [%d %d %d %d]\n",
 		obj->bbox.x1, obj->bbox.x2, obj->bbox.y1, obj->bbox.y2,
 		x0, x0+w, y0, y0+h);
 	return;
@@ -329,117 +329,56 @@
 
 // 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,prevc,counter;
-   int len;
-   int k;
-   int lastStripPosition;
-   int xsize;
-   int xmin=dxs,xmax=0;
-   int h,lasth;
-   int xtblc, utblc;
-   
-   obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
-
-   if(!vo_sub || !vo_font || !sub_visibility || (vo_font->font[40]<0)){
-       obj->flags&=~OSDFLAG_VISIBLE;
-       return;
-   }
-   
-   obj->bbox.y2=obj->y=dys;
-   obj->params.subtitle.lines=0;
-
-      // too long lines divide into a smaller ones
-      i=k=lasth=0;
-      h=vo_font->height;
-      lastStripPosition=-1;
-      l=vo_sub->lines;
-
-    {
-	struct osd_text_t *osl, *cp_ott, *tmp_ott, *tmp;
-	struct osd_text_p *otp_sub = NULL, *otp_sub_tmp,	// these are used to store the whole sub text osd
-	                  *otp, *tmp_otp, *pmt;	// these are used to manage sub text osd coming from a single sub line
-	int *char_seq, char_position, xlimit = dxs * sub_width_p / 100, counter;
-
-      while (l) {
-	    xsize = -vo_font->charspace;
-	  l--;
-	  t=vo_sub->text[i++];	  
-	  len=strlen(t)-1;
-	    char_position = 0;
-	    char_seq = (int *) malloc((len + 1) * sizeof(int));
-
-	  prevc = -1;
+int vo_preload_text_sub_lines(mp_osd_obj_t * obj, int start_line, int end_line, text_style_t *alignment, int loaded_chars)
+{
+    struct osd_text_t *osl, *cp_ott, *tmp_ott, *tmp;
+    struct osd_text_p *otp_sub = NULL, *otp_sub_tmp,	// these are used to store the whole sub text osd
+	*otp, *tmp_otp, *pmt;	// these are used to manage sub text osd coming from a single sub line
+    int *char_seq = NULL, char_position, xlimit = obj->dxs * sub_width_p / 100, counter, line_counter, line_length,
+	char_counter, line_height = 0, xsize, ysize;
+    unsigned char *line_text, prevchar, word_too_long;
+    
+    int xsizemax, line_x, line_y, block_x, block_y;
+    int utblc, xtblc, font, character, old_lines = obj->params.subtitle.lines;
 
-	    otp = NULL;
-	    osl = NULL;
-	    x = 1;
-
-	    // reading the subtitle words from vo_sub->text[]
-	  for (j=0;j<=len;j++){
-	      if ((c=t[j])>=0x80){
-		 if (sub_utf8){
-		    if ((c & 0xe0) == 0xc0)    /* 2 bytes U+00080..U+0007FF*/
-		       c = (c & 0x1f)<<6 | (t[++j] & 0x3f);
-		    else if((c & 0xf0) == 0xe0){ /* 3 bytes U+00800..U+00FFFF*/
-		       c = (((c & 0x0f)<<6) | (t[++j] & 0x3f))<<6;
-		       c |= (t[++j] & 0x3f);
-		    }
-		 } else if (sub_unicode) 
-		       c = (c<<8) + t[++j]; 
-	      }
-	      if (k==MAX_UCS){
-		 len=j; // end here
-		 mp_msg(MSGT_OSD,MSGL_WARN,"\nMAX_UCS exceeded!\n");
-	      }
-	      if (!c) c++; // avoid UCS 0
-	      render_one_glyph(vo_font, c);
-
-		if (c == ' ') {
-		    struct osd_text_t *tmp_ott = (struct osd_text_t *) calloc(1, sizeof(struct osd_text_t));
-
-		    if (osl == NULL) {
-			osl = cp_ott = tmp_ott;
-		    } else {
-			tmp_ott->prev = cp_ott;
-			cp_ott->next = tmp_ott;
-			tmp_ott->osd_kerning =
-			    vo_font->charspace + vo_font->width[' '];
-			cp_ott = tmp_ott;
-		    }
-		    tmp_ott->osd_length = xsize;
-		    tmp_ott->text_length = char_position;
-		    tmp_ott->text = (int *) malloc(char_position * sizeof(int));
-		    for (counter = 0; counter < char_position; ++counter)
-			tmp_ott->text[counter] = char_seq[counter];
-		    char_position = 0;
-		    xsize = 0;
-		    prevc = c;
-		} else {
-		    int delta_xsize = vo_font->width[c] + vo_font->charspace + kerning(vo_font, prevc, c);
-		    
-		    if (xsize + delta_xsize <= dxs) {
-			if (!x) x = 1;
-			prevc = c;
-			char_seq[char_position++] = c;
-			xsize += delta_xsize;
-			if ((!suboverlap_enabled) && ((font = vo_font->font[c]) >= 0)) {
-			    if (vo_font->pic_a[font]->h > h) {
-				h = vo_font->pic_a[font]->h;
-			    }
-			}
-		    } else {
-			if (x) {
-			    mp_msg(MSGT_OSD, MSGL_WARN, "\nSubtitle word '%s' too long!\n", t);
-			    x = 0;
-			}
+    line_y = 0;
+    // read each line and build splitting structure
+    for (line_counter = start_line ; line_counter < end_line; ++line_counter) {
+	xsize = -vo_font->charspace; // ??? perche' non da 0?
+	line_text = vo_sub->text[line_counter];
+	line_length = strlen(line_text) - 1;
+	char_position = 0;
+	if (char_seq != NULL) free(char_seq);
+	char_seq = (int *) malloc((line_length + 1) * sizeof(int));
+
+	prevchar = -1;
+
+	otp = NULL;
+	osl = NULL;
+	word_too_long = 0;
+
+	// reading the subtitle words from vo_sub->text[]
+	for (char_counter = 0; char_counter <= line_length; ++char_counter) {
+	    if ((character = line_text[char_counter]) >= 0x80) {
+		if (sub_utf8) {
+		    if ((character & 0xe0) == 0xc0)	/* 2 bytes U+00080..U+0007FF */
+			character = (character & 0x1f) << 6 | (line_text[++char_counter] & 0x3f);
+		    else if ((character & 0xf0) == 0xe0) {	/* 3 bytes U+00800..U+00FFFF */
+			character = (((character & 0x0f) << 6) | (line_text[++char_counter] & 0x3f)) << 6;
+			character |= (line_text[++char_counter] & 0x3f);
 		    }
-		}
-	    }// for len (all words from subtitle line read)
+		} else if (sub_unicode)
+		    character = (character << 8) + line_text[++char_counter];
+	    }
+	    if (loaded_chars == MAX_UCS) {
+		line_length = char_counter;	// end here
+		mp_msg(MSGT_OSD, MSGL_WARN, "\nMAX_UCS exceeded!\n");
+	    }
+	    if (!character)
+		character++;		// avoid UCS 0
+	    render_one_glyph(vo_font, character);
 
-	    // osl holds an ordered (as they appear in the lines) chain of the subtitle words
-	    {
+	    if (character == ' ') {
 		struct osd_text_t *tmp_ott = (struct osd_text_t *) calloc(1, sizeof(struct osd_text_t));
 
 		if (osl == NULL) {
@@ -447,8 +386,7 @@
 		} else {
 		    tmp_ott->prev = cp_ott;
 		    cp_ott->next = tmp_ott;
-		    tmp_ott->osd_kerning =
-			vo_font->charspace + vo_font->width[' '];
+		    tmp_ott->osd_kerning = vo_font->charspace + vo_font->width[' '];
 		    cp_ott = tmp_ott;
 		}
 		tmp_ott->osd_length = xsize;
@@ -457,242 +395,393 @@
 		for (counter = 0; counter < char_position; ++counter)
 		    tmp_ott->text[counter] = char_seq[counter];
 		char_position = 0;
-		xsize = -vo_font->charspace;
+		xsize = 0;
+		prevchar = character;
+	    } else {
+		int delta_xsize = vo_font->width[character] + vo_font->charspace + kerning(vo_font, prevchar, character);
+
+		if (xsize + delta_xsize <= obj->dxs) {
+		    word_too_long = 0;
+		    prevchar = character;
+		    char_seq[char_position++] = character;
+		    xsize += delta_xsize;
+		    if ((font = vo_font->font[character]) >= 0) {
+			if (vo_font->pic_a[font]->h > line_height) {
+			    line_height = vo_font->pic_a[font]->h;
+			}
+		    }
+		} else {
+		    if (!word_too_long) {
+			mp_msg(MSGT_OSD, MSGL_WARN, "\nSubtitle word '%s' too long!\n", line_text);
+			word_too_long = 1;
+		    }
+		}
 	    }
+	}// for line_length (all words from subtitle line read)
 
-	    if (osl != NULL) {
-		int value = 0, exit = 0, minimum = 0;
+	// osl holds an ordered (as they appear in the lines) chain of the subtitle words
+	{
+	    struct osd_text_t *tmp_ott = (struct osd_text_t *) calloc(1, sizeof(struct osd_text_t));
+
+	    if (osl == NULL) {
+		osl = cp_ott = tmp_ott;
+	    } else {
+		tmp_ott->prev = cp_ott;
+		cp_ott->next = tmp_ott;
+		tmp_ott->osd_kerning = vo_font->charspace + vo_font->width[' '];
+		cp_ott = tmp_ott;
+	    }
+	    tmp_ott->osd_length = xsize;
+	    tmp_ott->text_length = char_position;
+	    tmp_ott->text = (int *) malloc(char_position * sizeof(int));
+	    for (counter = 0; counter < char_position; ++counter)
+		tmp_ott->text[counter] = char_seq[counter];
+	    char_position = 0;
+	    xsize = -vo_font->charspace;
+	}
 
-		// otp will contain the chain of the osd subtitle lines coming from the single vo_sub line.
-		otp = tmp_otp = (struct osd_text_p *) calloc(1, sizeof(struct osd_text_p));
-		tmp_otp->ott = osl;
-		for (tmp_ott = tmp_otp->ott; exit == 0; ) {
-		    do {
-			value += tmp_ott->osd_kerning + tmp_ott->osd_length;
-			tmp_ott = tmp_ott->next;
-		    } while ((tmp_ott != NULL) && (value + tmp_ott->osd_kerning + tmp_ott->osd_length <= xlimit));
-		    if (tmp_ott != NULL) {
-			struct osd_text_p *tmp = (struct osd_text_p *) calloc(1, sizeof(struct osd_text_p));
-
-			tmp_otp->value = value;
-			tmp_otp->next = tmp;
-			tmp->prev = tmp_otp;
-			tmp_otp = tmp;
-			tmp_otp->ott = tmp_ott;
-			value = -2 * vo_font->charspace - vo_font->width[' '];
-		    } else {
-			tmp_otp->value = value;
-			exit = 1;
-		    }
+	if (osl != NULL) {
+	    int value = 0, exit = 0, minimum = 0;
+
+	    // otp will contain the chain of the osd subtitle lines coming from the single vo_sub line.
+	    otp = tmp_otp = (struct osd_text_p *) calloc(1, sizeof(struct osd_text_p));
+	    tmp_otp->ott = osl;
+	    for (tmp_ott = tmp_otp->ott; exit == 0;) {
+		do {
+		    value += tmp_ott->osd_kerning + tmp_ott->osd_length;
+		    tmp_ott = tmp_ott->next;
+		} while ((tmp_ott != NULL) && (value + tmp_ott->osd_kerning + tmp_ott->osd_length <= xlimit));
+		if (tmp_ott != NULL) {
+		    struct osd_text_p *tmp = (struct osd_text_p *) calloc(1, sizeof(struct osd_text_p));
+
+		    tmp_otp->value = value;
+		    tmp_otp->next = tmp;
+		    tmp->prev = tmp_otp;
+		    tmp_otp = tmp;
+		    tmp_otp->ott = tmp_ott;
+		    value = -2 * vo_font->charspace - vo_font->width[' '];
+		} else {
+		    tmp_otp->value = value;
+		    exit = 1;
 		}
+		tmp_otp->value += vo_font->width[' '];
+	    }
 
 
 #ifdef NEW_SPLITTING
-		// minimum holds the 'sum of the differences in lenght among the lines',
-		// a measure of the eveness of the lenghts of the lines
-		for (tmp_otp = otp; tmp_otp->next != NULL; tmp_otp = tmp_otp->next) {
-		    pmt = tmp_otp->next;
-		    while (pmt != NULL) {
-			minimum += abs(tmp_otp->value - pmt->value);
-			pmt = pmt->next;
-		    }
+	    // minimum holds the 'sum of the differences in lenght among the lines',
+	    // a measure of the eveness of the lenghts of the lines
+	    for (tmp_otp = otp; tmp_otp->next != NULL; tmp_otp = tmp_otp->next) {
+		pmt = tmp_otp->next;
+		while (pmt != NULL) {
+		    minimum += abs(tmp_otp->value - pmt->value);
+		    pmt = pmt->next;
 		}
+	    }
 
-		if (otp->next != NULL) {
-		    int mem1, mem2;
-		    struct osd_text_p *mem, *hold;
-
-		    exit = 0;
-		    // until the last word of a line can be moved to the beginning of following line
-		    // reducing the 'sum of the differences in lenght among the lines', it is done
-		    while (exit == 0) {
-			hold = NULL;
-			exit = 1;
-			for (tmp_otp = otp; tmp_otp->next != NULL; tmp_otp = tmp_otp->next) {
-			    pmt = tmp_otp->next;
-			    for (tmp = tmp_otp->ott; tmp->next != pmt->ott; tmp = tmp->next);
-			    if (pmt->value + tmp->osd_length + pmt->ott->osd_kerning <= xlimit) {
-				mem1 = tmp_otp->value;
-				mem2 = pmt->value;
-				tmp_otp->value = mem1 - tmp->osd_length - tmp->osd_kerning;
-				pmt->value = mem2 + tmp->osd_length + pmt->ott->osd_kerning;
-
-				value = 0;
-				for (mem = otp; mem->next != NULL; mem = mem->next) {
-				    pmt = mem->next;
-				    while (pmt != NULL) {
-					value += abs(mem->value - pmt->value);
-					pmt = pmt->next;
-				    }
-				}
-				if (value < minimum) {
-				    minimum = value;
-				    hold = tmp_otp;
-				    exit = 0;
-				}
-				tmp_otp->value = mem1;
-				tmp_otp->next->value = mem2;
-			    }
-			}
-			// merging
-			if (exit == 0) {
-			    tmp_otp = hold;
-			    pmt = tmp_otp->next;
-			    for (tmp = tmp_otp->ott; tmp->next != pmt->ott; tmp = tmp->next);
+	    if (otp->next != NULL) {
+		int mem1, mem2;
+		struct osd_text_p *mem, *hold;
+
+		exit = 0;
+		// until the last word of a line can be moved to the beginning of following line
+		// reducing the 'sum of the differences in lenght among the lines', it is done
+		while (exit == 0) {
+		    hold = NULL;
+		    exit = 1;
+		    for (tmp_otp = otp; tmp_otp->next != NULL; tmp_otp = tmp_otp->next) {
+			pmt = tmp_otp->next;
+			for (tmp = tmp_otp->ott; tmp->next != pmt->ott; tmp = tmp->next);
+			if (pmt->value + tmp->osd_length + pmt->ott->osd_kerning <= xlimit) {
 			    mem1 = tmp_otp->value;
 			    mem2 = pmt->value;
 			    tmp_otp->value = mem1 - tmp->osd_length - tmp->osd_kerning;
 			    pmt->value = mem2 + tmp->osd_length + pmt->ott->osd_kerning;
-			    pmt->ott = tmp;
-			}//~merging
-		    }//~while(exit == 0)
-		}//~if(otp->next!=NULL)
+
+			    value = 0;
+			    for (mem = otp; mem->next != NULL; mem = mem->next) {
+				pmt = mem->next;
+				while (pmt != NULL) {
+				    value += abs(mem->value - pmt->value);
+				    pmt = pmt->next;
+				}
+			    }
+			    if (value < minimum) {
+				minimum = value;
+				hold = tmp_otp;
+				exit = 0;
+			    }
+			    tmp_otp->value = mem1;
+			    tmp_otp->next->value = mem2;
+			}
+		    }
+		    // merging
+		    if (exit == 0) {
+			tmp_otp = hold;
+			pmt = tmp_otp->next;
+			for (tmp = tmp_otp->ott; tmp->next != pmt->ott; tmp = tmp->next);
+			mem1 = tmp_otp->value;
+			mem2 = pmt->value;
+			tmp_otp->value = mem1 - tmp->osd_length - tmp->osd_kerning;
+			pmt->value = mem2 + tmp->osd_length + pmt->ott->osd_kerning;
+			pmt->ott = tmp;
+		    }		//~merging
+		}		//~while(exit == 0)
+	    }			//~if(otp->next!=NULL)
 #endif
 
-		// adding otp (containing splitted lines) to otp chain
-		if (otp_sub == NULL) {
-		    otp_sub = otp;
-		    for (otp_sub_tmp = otp_sub; otp_sub_tmp->next != NULL; otp_sub_tmp = otp_sub_tmp->next);
-		} else {
-		    //updating ott chain
-		    tmp = otp_sub->ott;
-		    while (tmp->next != NULL) tmp = tmp->next;
-		    tmp->next = otp->ott;
-		    otp->ott->prev = tmp;
-		    //attaching new subtitle line at the end
-		    otp_sub_tmp->next = otp;
-		    otp->prev = otp_sub_tmp;
-		    do
-			otp_sub_tmp = otp_sub_tmp->next;
-		    while (otp_sub_tmp->next != NULL);
-		}
-	    }//~ if(osl != NULL)
-	} // while
+	    // adding otp (containing splitted lines) to otp chain
+	    if (otp_sub == NULL) {
+		otp_sub = otp;
+		for (otp_sub_tmp = otp_sub; otp_sub_tmp->next != NULL; otp_sub_tmp = otp_sub_tmp->next);
+	    } else {
+		//updating ott chain
+		tmp = otp_sub->ott;
+		while (tmp->next != NULL)
+		    tmp = tmp->next;
+		tmp->next = otp->ott;
+		otp->ott->prev = tmp;
+		//attaching new subtitle line at the end
+		otp_sub_tmp->next = otp;
+		otp->prev = otp_sub_tmp;
+		do
+		    otp_sub_tmp = otp_sub_tmp->next;
+		while (otp_sub_tmp->next != NULL);
+	    }
+	}			//~ if(osl != NULL)
+    }// for (read each line)
+
+    // write lines into utbl
+    xtblc = obj->params.subtitle.lines;
+    for(counter = 0, utblc = 0; counter < xtblc ; ++utblc) {
+	if (!obj->params.subtitle.utbl[utblc]) {
+	    ++counter;
+	}
+    }
 
-	// write lines into utbl
-	xtblc = 0;
-	utblc = 0;
-	obj->y = dys;
-	obj->params.subtitle.lines = 0;
+    {
+	// this calculates the maximum lenght of a line in the current subs
+	// this takes into account also block horizontal alignment
+	ysize = xsizemax = 0;
 	for (tmp_otp = otp_sub; tmp_otp != NULL; tmp_otp = tmp_otp->next) {
+	    if (tmp_otp->value > xsizemax) xsizemax = tmp_otp->value;
+	    ysize += vo_font->height;
+	}
+	ysize += (vo_font->pic_a[vo_font->font[40]]->h - vo_font->height);
+	if (alignment) {
+	    if (alignment->alignment == SUB_ALIGNMENT_POSITIONAL) {
+		block_x = alignment->posx;
+		block_y = alignment->posy;
+	    } else {
+		switch (alignment->alignment&SUB_ALIGNMENT_HORIZONTAL) {
+	        case SUB_ALIGNMENT_PHLEFT:
+	            block_x = 1;
+	            break;
+	        case SUB_ALIGNMENT_PHRIGHT:
+	            block_x = obj->dxs - xsizemax;
+	            break;
+	        case SUB_ALIGNMENT_PHCENTER:
+	        default:
+	            block_x = (obj->dxs - xsizemax) / 2;
+	            break;
+	        }
+	        switch (alignment->alignment&SUB_ALIGNMENT_VERTICAL) {
+	        case SUB_ALIGNMENT_PVTOP:
+	            block_y = 1;
+	            break;
+	        case SUB_ALIGNMENT_PVMIDDLE:
+	            block_y = (obj->dys - ysize) / 2;
+	            break;
+	        case SUB_ALIGNMENT_PVBOTTOM:
+	        default:
+	            block_y = obj->dys - ysize;
+	            break;
+	        }
+	    }
+	} else { // alignment is NULL
+	    block_x = (obj->dxs - xsizemax) / 2;
+	    block_y = obj->dys - ysize;
+	}
+    }
+    for (tmp_otp = otp_sub; tmp_otp != NULL; tmp_otp = tmp_otp->next) {
 
-	    if ((obj->params.subtitle.lines++) >= MAX_UCSLINES)
-		break;
+	if ((obj->params.subtitle.lines++) >= MAX_UCSLINES)
+	    break;
 
-	    if (h > obj->y) {	// out of the screen so end parsing
-		obj->y -= lasth - vo_font->height;	// correct the y position
-		break;
-	    }
-	    xsize = tmp_otp->value;
-	    obj->params.subtitle.xtbl[xtblc++] = (dxs - xsize) / 2;
-	    if (xmin > (dxs - xsize) / 2)
-		xmin = (dxs - xsize) / 2;
-	    if (xmax < (dxs + xsize) / 2)
-		xmax = (dxs + xsize) / 2;
-
-	    tmp = (tmp_otp->next == NULL) ? NULL : tmp_otp->next->ott;
-	    for (tmp_ott = tmp_otp->ott; tmp_ott != tmp; tmp_ott = tmp_ott->next) {
-		for (counter = 0; counter < tmp_ott->text_length; ++counter) {
-		    if (utblc > MAX_UCS) {
-			break;
-		    }
-		    c = tmp_ott->text[counter];
-		    render_one_glyph(vo_font, c);
-		    obj->params.subtitle.utbl[utblc++] = c;
-		    k++;
-		}
-		obj->params.subtitle.utbl[utblc++] = ' ';
+	if (line_height > obj->y) {	// out of the screen so end parsing
+	    obj->y += vo_font->height;	// correct the y position
+	    break;
+	}
+	xsize = tmp_otp->value; //xsize of the current line
+	if (alignment) {
+	    switch (alignment->alignment&SUB_ALIGNMENT_BLOCK) {
+	    case SUB_ALIGNMENT_BLEFT:
+	    case SUB_ALIGNMENT_BJUSTIFY:
+	        // left
+	        line_x = 0;
+	        break;
+	    case SUB_ALIGNMENT_BRIGHT:
+	        // right
+	        line_x = xsizemax - xsize;
+	        break;
+	    case SUB_ALIGNMENT_BCENTER:
+	    default:
+	        //center or justify
+	        line_x = (xsizemax - xsize) / 2;
 	    }
-	    obj->params.subtitle.utbl[utblc - 1] = 0;
-	    obj->y -= vo_font->height;
+	} else { // no alignment
+	    line_x = (xsizemax - xsize) / 2;
 	}
-	if(obj->params.subtitle.lines)
-	    obj->y = dys - ((obj->params.subtitle.lines - 1) * vo_font->height + vo_font->pic_a[vo_font->font[40]]->h);
-	
-	// free memory
-	if (otp_sub != NULL) {
-	    for (tmp = otp_sub->ott; tmp->next != NULL; free(tmp->prev)) {
-		free(tmp->text);
-		tmp = tmp->next;
+
+	tmp = (tmp_otp->next == NULL) ? NULL : tmp_otp->next->ott;
+	for (tmp_ott = tmp_otp->ott; tmp_ott != tmp; tmp_ott = tmp_ott->next) {
+	    for (counter = 0; counter < tmp_ott->text_length; ++counter) {
+		if (utblc > MAX_UCS) {
+		    break;
+		}
+		character = tmp_ott->text[counter];
+		render_one_glyph(vo_font, character);
+		obj->params.subtitle.utbl[utblc++] = character;
+		++loaded_chars;
 	    }
+	    if (utblc > MAX_UCS) break;
+	    obj->params.subtitle.utbl[utblc++] = ' ';
+	}
+	obj->params.subtitle.utbl[utblc - 1] = 0;
+	if (xtblc == 0 || obj->params.subtitle.ftbl[xtblc - 1] != alignment->font_string)
+	    obj->params.subtitle.ftbl[xtblc] = alignment->font_string;
+	else
+	    obj->params.subtitle.ftbl[xtblc] = NULL;
+	obj->params.subtitle.ytbl[xtblc] = line_y;
+	obj->params.subtitle.xtbl[xtblc++] = line_x;
+	line_y += vo_font->height;
+    }
+
+    // merge current sublines in obj
+    if (block_x + xsizemax >  obj->bbox.x2) obj->bbox.x2 = block_x + xsizemax;
+    if (block_y + ysize    >  obj->bbox.y2) obj->bbox.y2 = block_y + ysize   ;
+    if (block_x < obj->bbox.x1) {
+	int delta_x = obj->bbox.x1 - block_x;
+	for (counter = 0 ; counter < old_lines ; ++counter)
+	    obj->params.subtitle.xtbl[counter] += delta_x;
+	obj->bbox.x1 = block_x;
+    } else if (block_x > obj->bbox.x1) {
+	int delta_x = block_x - obj->bbox.x1;
+	for (counter = old_lines ; counter < obj->params.subtitle.lines ; ++counter)
+	    obj->params.subtitle.xtbl[counter] += delta_x;
+    }
+    if (block_y < obj->bbox.y1) {
+	int delta_y = obj->bbox.y1 - block_y;
+	for (counter = 0 ; counter < old_lines ; ++counter)
+	    obj->params.subtitle.ytbl[counter] += delta_y;
+	obj->bbox.y1 = block_y;
+    } else if (block_y > obj->bbox.y1) {
+	int delta_y = block_y - obj->bbox.y1;
+	for (counter = old_lines ; counter < obj->params.subtitle.lines ; ++counter)
+	    obj->params.subtitle.ytbl[counter] += delta_y;
+    }
+
+    // free memory
+    if (otp_sub != NULL) {
+	for (tmp = otp_sub->ott; tmp->next != NULL; free(tmp->prev)) {
 	    free(tmp->text);
-	    free(tmp);
-	
-	    for(pmt = otp_sub; pmt->next != NULL; free(pmt->prev)) {
-		pmt = pmt->next;
+	    tmp = tmp->next;
+	}
+	free(tmp->text);
+	free(tmp);
+
+	for (pmt = otp_sub; pmt->next != NULL; free(pmt->prev)) {
+	    pmt = pmt->next;
+	}
+	free(pmt);
+    }
+    return loaded_chars;
+}
+
+inline static void vo_update_text_sub(mp_osd_obj_t* obj,int dxs,int dys){
+   int c, utblc, xtblc, j, l, x, y, font, prevc, counter, loaded_chars;
+   text_style_t *previous_style;
+   char *previous_font_string = NULL, *current_font_string;
+   
+   obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
+
+   if(!vo_sub || !vo_font || !sub_visibility || (vo_font->font[40]<0)){
+       obj->flags&=~OSDFLAG_VISIBLE;
+       return;
+   }
+   
+
+    obj->y = dys;
+    obj->bbox.y2 = obj->bbox.x2 = 0;
+    obj->bbox.y1 = obj->dys = dys;
+    obj->bbox.x1 = obj->dxs = dxs;
+    obj->params.subtitle.lines=0;
+    obj->params.subtitle.utbl[0] = 0;
+
+    loaded_chars = 0;
+    if (vo_sub->text_style[0] == NULL) vo_sub->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    for (counter = 1, previous_style = vo_sub->text_style[0], prevc = 0 ; counter < vo_sub->lines ; ++counter) {
+
+	if (vo_sub->text_style[counter] == NULL) continue;
+	// this means that current and previous lines have different styles/positions, let's draw the previous
+	if (!previous_style ||
+	    previous_style->alignment != (char)SUB_ALIGNMENT_FAKE) {
+#ifdef HAVE_FREETYPE
+	    current_font_string = (previous_style->font_string) ? previous_style->font_string : font_name;
+	    if ((previous_font_string || current_font_string) || ((previous_font_string && current_font_string) && strcmp(previous_font_string, current_font_string) !=0)) {
+	        load_font_ft(obj->dxs, obj->dys, current_font_string, previous_style->font_point_size);
+	        if (previous_font_string) {
+		    free (previous_font_string);
+		    previous_font_string = NULL;
+	        }
+	        if (current_font_string) previous_font_string = strdup(current_font_string);
 	    }
-	    free(pmt);
+#endif
+	    loaded_chars = vo_preload_text_sub_lines(obj, prevc, counter, previous_style, loaded_chars);
 	}
-	
+	previous_style = vo_sub->text_style[counter];
+	prevc          = counter;
+    }
+#ifdef HAVE_FREETYPE
+    current_font_string = (previous_style->font_string) ? previous_style->font_string : font_name;
+    //if (!(!previous_font_string && !current_font_string) || ((!previous_font_string && !current_font_string) && strcmp(previous_font_string, current_font_string) !=0)) {
+    if ((previous_font_string || current_font_string) || ((previous_font_string && current_font_string) && strcmp(previous_font_string, current_font_string) !=0)) {
+	load_font_ft(obj->dxs, obj->dys, current_font_string, previous_style->font_point_size);
+	if (previous_font_string) {
+	    free (previous_font_string);
+	    previous_font_string = NULL;
+	}
+	if (current_font_string) previous_font_string = strdup(current_font_string);
+    }
+#endif
+    if (previous_style->alignment != (char)SUB_ALIGNMENT_FAKE) {
+	loaded_chars = vo_preload_text_sub_lines(obj, prevc, counter, previous_style, loaded_chars);
     }
-    /// vertical alignment
-    h = dys - obj->y;
-    if (sub_alignment == 2)
-        obj->y = dys * sub_pos / 100 - h;
-    else if (sub_alignment == 1)
-        obj->y = dys * sub_pos / 100 - h / 2;
-    else
-        obj->y = dys * sub_pos / 100;
-
-    if (obj->y < 0)
-        obj->y = 0;
-    if (obj->y > dys - h)
-        obj->y = dys - h;
-
-    obj->bbox.y2 = obj->y + h;
-
-    // calculate bbox:
-    if (sub_justify) xmin = 10;
-    obj->bbox.x1=xmin;
-    obj->bbox.x2=xmax;
-    obj->bbox.y1=obj->y;
-//    obj->bbox.y2=obj->y+obj->params.subtitle.lines*vo_font->height;
+#ifdef HAVE_FREETYPE
+//load_font_ft(obj->dxs, obj->dys, font_name, -1);
+#endif
+
     obj->flags|=OSDFLAG_BBOX;
 
     alloc_buf(obj);
 
-    y = obj->y;
-    
-    obj->alignment = 0;
-    switch(vo_sub->alignment) {
-       case SUB_ALIGNMENT_BOTTOMLEFT:
-       case SUB_ALIGNMENT_MIDDLELEFT:
-       case SUB_ALIGNMENT_TOPLEFT:
-	    obj->alignment |= 0x1;
-	    break;
-       case SUB_ALIGNMENT_BOTTOMRIGHT:
-       case SUB_ALIGNMENT_MIDDLERIGHT:
-       case SUB_ALIGNMENT_TOPRIGHT:
-	    obj->alignment |= 0x2;
-	    break;
-       case SUB_ALIGNMENT_BOTTOMCENTER:
-       case SUB_ALIGNMENT_MIDDLECENTER:
-       case SUB_ALIGNMENT_TOPCENTER:
-	default:
-	    obj->alignment |= 0x0;
-    }
-
-    i=j=0;
     if ((l = obj->params.subtitle.lines)) {
-	for(counter = dxs; i < l; ++i)
-	    if (obj->params.subtitle.xtbl[i] < counter) counter = obj->params.subtitle.xtbl[i];
-	for (i = 0; i < l; ++i) {
-	    switch (obj->alignment&0x3) {
-		case 1:
-		    // left
-		    x = counter;
-		    break;
-		case 2:
-		    // right
-		    x = 2 * obj->params.subtitle.xtbl[i] - counter - ((obj->params.subtitle.xtbl[i] == counter) ? 0 : 1);
-		    break;
-		default:
-		    //center
-		    x = obj->params.subtitle.xtbl[i];
+	for ( j = xtblc = utblc = counter = 0 ; counter < l ; ++counter ) {
+	    x = obj->bbox.x1 + obj->params.subtitle.xtbl[counter];
+	    y = obj->bbox.y1 + obj->params.subtitle.ytbl[counter];
+#ifdef HAVE_FREETYPE
+	    if (obj->params.subtitle.ftbl[counter] != NULL) {
+		char *temp = strstr(obj->params.subtitle.ftbl[counter], "-");
+		int font_point_size = (int)strtol(temp, (char **)NULL, 10) * -1;
+		load_font_ft(obj->dxs, obj->dys, obj->params.subtitle.ftbl[counter], font_point_size);
 	    }
-	 prevc = -1;
-	 while ((c=obj->params.subtitle.utbl[j++])){
+#endif
+	    prevc = -1;
+	    while ((c=obj->params.subtitle.utbl[j++])){
 	       x += kerning(vo_font,prevc,c);
+#ifdef HAVE_FREETYPE
+		render_one_glyph(vo_font, c);
+#endif
 	       if ((font=vo_font->font[c])>=0)
 		  draw_alpha_buf(obj,x,y,
 			     vo_font->width[c],
@@ -703,10 +792,11 @@
 	       x+=vo_font->width[c]+vo_font->charspace;
                prevc = c;
 	    }
-         y+=vo_font->height;
 	}
     }
-    
+#ifdef HAVE_FREETYPE
+load_font_ft(obj->dxs, obj->dys, font_name, -1);
+#endif
 }
 
 inline static void vo_update_spudec_sub(mp_osd_obj_t* obj, int dxs, int dys)
@@ -766,7 +856,7 @@
     // here is the right place to get screen dimensions
     if (!vo_font || force_load_font) {
 	force_load_font = 0;
-	load_font_ft(dxs, dys);
+	load_font_ft(dxs, dys, font_name, -1);
     }
 #endif
 
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/libvo/sub.h MPlayer-20050307.patch/libvo/sub.h
--- MPlayer-20050307/libvo/sub.h	2004-10-28 03:15:52.000000000 +0200
+++ MPlayer-20050307.patch/libvo/sub.h	2005-03-09 15:51:34.000000000 +0100
@@ -34,6 +34,8 @@
 	    void* sub;			// value of vo_sub at last update
 	    int utbl[MAX_UCS+1];	// subtitle text
 	    int xtbl[MAX_UCSLINES];	// x positions
+	    int ytbl[MAX_UCSLINES];	// y positions
+	    char *ftbl[MAX_UCSLINES];	// fonts
 	    int lines;			// no. of lines
 	} subtitle;
 	struct {
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/mencoder.c MPlayer-20050307.patch/mencoder.c
--- MPlayer-20050307/mencoder.c	2005-03-01 21:21:58.000000000 +0100
+++ MPlayer-20050307.patch/mencoder.c	2005-03-29 00:13:21.000000000 +0200
@@ -585,12 +585,12 @@
 // check .sub
 //  current_module="read_subtitles_file";
   if(sub_name && sub_name[0]){
-    subdata=sub_read_file(sub_name[0], sh_video->fps);
+    subdata=sub_read_file(sub_name[0], sh_video->fps, sh_video->disp_w, sh_video->disp_h);
     if(!subdata) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name[0]);
   } else
   if(sub_auto) { // auto load sub file ...
     subdata=sub_read_file( filename ? sub_filenames( get_path("sub/"), filename )[0]
-	                              : "default.sub", sh_video->fps );
+	                              : "default.sub", sh_video->fps, sh_video->disp_w, sh_video->disp_h);
   }
 #endif	
 
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/mplayer.c MPlayer-20050307.patch/mplayer.c
--- MPlayer-20050307/mplayer.c	2005-03-29 23:31:49.708121200 +0200
+++ MPlayer-20050307.patch/mplayer.c	2005-03-29 00:12:25.000000000 +0200
@@ -296,7 +296,7 @@
 extern int vo_flags;
 
 // sub:
-char *font_name=NULL;
+extern char *font_name=NULL;
 #ifdef HAVE_FONTCONFIG
 extern int font_fontconfig;
 #endif
@@ -762,7 +762,7 @@
 	return;
     }
 
-    subd = sub_read_file(filename, fps);
+    subd = sub_read_file(filename, fps, sh_video->disp_w, sh_video->disp_h);
     if(!subd && !silent) 
         mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CantLoadSub, filename);
     if (subd == NULL || set_of_sub_size >= MAX_SUBTITLE_FILES) return;
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/subreader.c MPlayer-20050307.patch/subreader.c
--- MPlayer-20050307/subreader.c	2005-02-04 19:31:03.000000000 +0100
+++ MPlayer-20050307.patch/subreader.c	2005-03-29 00:26:42.000000000 +0200
@@ -38,11 +38,11 @@
 
 extern char* dvdsub_lang;
 
-/* Maximal length of line of a subtitle */
-#define LINE_LEN 1000
 static float mpsub_position=0;
 static float mpsub_multiplier=1.;
 static int sub_slacktime = 20000; //20 sec
+int	disp_w, disp_h;
+char *font_name;
 
 int sub_no_text_pp=0;   // 1 => do not apply text post-processing
                         // like {\...} elimination in SSA format.
@@ -95,18 +95,18 @@
 }
 
 subtitle *sub_read_line_sami(FILE *fd, subtitle *current) {
-    static char line[LINE_LEN+1];
+    static char line[SUB_LINE_LENGTH+1];
     static char *s = NULL, *slacktime_s;
-    char text[LINE_LEN+1], *p=NULL, *q;
+    char text[SUB_LINE_LENGTH+1], *p=NULL, *q, previous_alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;
     int state;
 
     current->lines = current->start = current->end = 0;
-    current->alignment = SUB_ALIGNMENT_BOTTOMCENTER;
+    current->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;
     state = 0;
 
     /* read the first line */
     if (!s)
-	    if (!(s = fgets(line, LINE_LEN, fd))) return 0;
+	    if (!(s = fgets(line, SUB_LINE_LENGTH, fd))) return 0;
 
     do {
 	switch (state) {
@@ -146,8 +146,20 @@
 	    if (*s == '\0') break;
 	    else if (!strncasecmp (s, "<br>", 4)) {
 		*p = '\0'; p = text; trail_space (text);
-		if (text[0] != '\0')
+		if (text[0] != '\0') {
+		    if (current->lines == 0) {
+			previous_alignment = current->alignment;
+			current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+			current->text_style[0]->alignment = current->alignment;
+		    } else if (current->alignment != previous_alignment) {
+			previous_alignment = current->alignment;
+			current->text_style[current->lines] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+			current->text_style[current->lines]->alignment = current->alignment;
+		    } else {
+			current->text_style[current->lines] = NULL;
+		    }
 		    current->text[current->lines++] = strdup (text);
+		}
 		s += 4;
 	    }
 	    else if ((*s == '{') && !sub_no_text_pp) { state = 5; ++s; continue; }
@@ -167,8 +179,20 @@
 	    if (q) {
 		current->end = strtol (q + 6, &q, 0) / 10 - 1;
 		*p = '\0'; trail_space (text);
-		if (text[0] != '\0')
+		if (text[0] != '\0') {
+		    if (current->lines == 0) {
+			previous_alignment = current->alignment;
+			current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+			current->text_style[0]->alignment = current->alignment;
+		    } else if (current->alignment != previous_alignment) {
+			previous_alignment = current->alignment;
+			current->text_style[current->lines] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+			current->text_style[current->lines]->alignment = current->alignment;
+		    } else {
+			current->text_style[current->lines] = NULL;
+		    }
 		    current->text[current->lines++] = strdup (text);
+		}
 		if (current->lines > 0) { state = 99; break; }
 		state = 0; continue;
 	    }
@@ -177,35 +201,9 @@
 	    break;
        case 5: /* get rid of {...} text, but read the alignment code */
 	    if ((*s == '\\') && (*(s + 1) == 'a') && !sub_no_text_pp) {
-               if (stristr(s, "\\a1") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_BOTTOMLEFT;
-                   s = s + 3;
-               }
-               if (stristr(s, "\\a2") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_BOTTOMCENTER;
-                   s = s + 3;
-               } else if (stristr(s, "\\a3") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_BOTTOMRIGHT;
-                   s = s + 3;
-               } else if ((stristr(s, "\\a4") != NULL) || (stristr(s, "\\a5") != NULL) || (stristr(s, "\\a8") != NULL)) {
-                   current->alignment = SUB_ALIGNMENT_TOPLEFT;
-                   s = s + 3;
-               } else if (stristr(s, "\\a6") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_TOPCENTER;
-                   s = s + 3;
-               } else if (stristr(s, "\\a7") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_TOPRIGHT;
-                   s = s + 3;
-               } else if (stristr(s, "\\a9") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_MIDDLELEFT;
-                   s = s + 3;
-               } else if (stristr(s, "\\a10") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_MIDDLECENTER;
-                   s = s + 4;
-               } else if (stristr(s, "\\a11") != NULL) {
-                   current->alignment = SUB_ALIGNMENT_MIDDLERIGHT;
-                   s = s + 4;
-               }
+		int alignment_number = 2;
+		sscanf(s + 2, "%d", &alignment_number);
+		sub_ssa_alignment(0, alignment_number, &current->alignment);
 	    }
 	    if (*s == '}') state = 3;
 	    ++s;
@@ -213,7 +211,7 @@
 	}
 
 	/* read next line */
-	if (state != 99 && !(s = fgets (line, LINE_LEN, fd))) {
+	if (state != 99 && !(s = fgets (line, SUB_LINE_LENGTH, fd))) {
 	    if (current->start > 0) {
 		break; // if it is the last subtitle
 	    } else {
@@ -227,8 +225,20 @@
     if (current->end <= 0) {
         current->end = current->start + sub_slacktime;
 	*p = '\0'; trail_space (text);
-	if (text[0] != '\0')
+	if (text[0] != '\0') {
+	    if (current->lines == 0) {
+		previous_alignment = current->alignment;
+		current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+		current->text_style[0]->alignment = current->alignment;
+	    } else if (current->alignment != previous_alignment) {
+		previous_alignment = current->alignment;
+		current->text_style[current->lines] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+		current->text_style[current->lines]->alignment = current->alignment;
+	    } else {
+		current->text_style[current->lines] = NULL;
+	    }
 	    current->text[current->lines++] = strdup (text);
+	}
     }
     
     return current;
@@ -258,13 +268,13 @@
 }
 
 subtitle *sub_read_line_microdvd(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
-    char line2[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
+    char line2[SUB_LINE_LENGTH+1];
     char *p, *next;
     int i;
 
     do {
-	if (!fgets (line, LINE_LEN, fd)) return NULL;
+	if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
     } while ((sscanf (line,
 		      "{%ld}{}%[^\r\n]",
 		      &(current->start), line2) < 2) &&
@@ -282,17 +292,19 @@
     }
     current->lines= ++i;
 
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
 subtitle *sub_read_line_mpl2(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
-    char line2[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
+    char line2[SUB_LINE_LENGTH+1];
     char *p, *next;
     int i;
 
     do {
-	if (!fgets (line, LINE_LEN, fd)) return NULL;
+	if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
     } while ((sscanf (line,
 		      "[%ld][%ld]%[^\r\n]",
 		      &(current->start), &(current->end), line2) < 3));
@@ -308,22 +320,24 @@
     }
     current->lines= ++i;
 
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
 subtitle *sub_read_line_subrip(FILE *fd, subtitle *current) {
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     int a1,a2,a3,a4,b1,b2,b3,b4;
     char *p=NULL, *q=NULL;
     int len;
     
     while (1) {
-	if (!fgets (line, LINE_LEN, fd)) return NULL;
+	if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
 	if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) continue;
 	current->start = a1*360000+a2*6000+a3*100+a4;
 	current->end   = b1*360000+b2*6000+b3*100+b4;
 
-	if (!fgets (line, LINE_LEN, fd)) return NULL;
+	if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
 
 	p=q=line;
 	for (current->lines=1; current->lines < SUB_MAX_TEXT; current->lines++) {
@@ -338,23 +352,26 @@
 	}
 	break;
     }
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
 subtitle *sub_read_line_subviewer(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     int a1,a2,a3,a4,b1,b2,b3,b4;
     char *p=NULL;
     int i,len;
     
     while (!current->text[0]) {
-	if (!fgets (line, LINE_LEN, fd)) return NULL;
+	if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
 	if ((len=sscanf (line, "%d:%d:%d%[,.:]%d --> %d:%d:%d%[,.:]%d",&a1,&a2,&a3,(char *)&i,&a4,&b1,&b2,&b3,(char *)&i,&b4)) < 10)
 	    continue;
 	current->start = a1*360000+a2*6000+a3*100+a4/10;
 	current->end   = b1*360000+b2*6000+b3*100+b4/10;
+	current->alignment = SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;
 	for (i=0; i<SUB_MAX_TEXT;) {
-	    if (!fgets (line, LINE_LEN, fd)) break;
+	    if (!fgets (line, SUB_LINE_LENGTH, fd)) break;
 	    len=0;
 	    for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++);
 	    if (len) {
@@ -387,24 +404,26 @@
 	}
 	current->lines=i;
     }
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = current->alignment;
     return current;
 }
 
 subtitle *sub_read_line_subviewer2(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     int a1,a2,a3,a4;
     char *p=NULL;
     int i,len;
    
     while (!current->text[0]) {
-        if (!fgets (line, LINE_LEN, fd)) return NULL;
+        if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
 	if (line[0]!='{')
 	    continue;
         if ((len=sscanf (line, "{T %d:%d:%d:%d",&a1,&a2,&a3,&a4)) < 4)
             continue;
         current->start = a1*360000+a2*6000+a3*100+a4/10;
         for (i=0; i<SUB_MAX_TEXT;) {
-            if (!fgets (line, LINE_LEN, fd)) break;
+            if (!fgets (line, SUB_LINE_LENGTH, fd)) break;
             if (line[0]=='}') break;
             len=0;
             for (p=line; *p!='\n' && *p!='\r' && *p; ++p,++len);
@@ -419,18 +438,20 @@
         }
         current->lines=i;
     }
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
 
 subtitle *sub_read_line_vplayer(FILE *fd,subtitle *current) {
-	char line[LINE_LEN+1];
+	char line[SUB_LINE_LENGTH+1];
 	int a1,a2,a3;
 	char *p=NULL, *next,separator;
 	int i,len,plen;
 
 	while (!current->text[0]) {
-		if (!fgets (line, LINE_LEN, fd)) return NULL;
+		if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
 		if ((len=sscanf (line, "%d:%d:%d%c%n",&a1,&a2,&a3,&separator,&plen)) < 4)
 			continue;
 		
@@ -466,6 +487,8 @@
 			current->lines=i+1;
 		}
 	}
+	current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+	current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
 	return current;
 }
 
@@ -473,13 +496,13 @@
 	//TODO: This format uses quite rich (sub/super)set of xhtml 
 	// I couldn't check it since DTD is not included.
 	// WARNING: full XML parses can be required for proper parsing 
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     int a1,a2,a3,a4,b1,b2,b3,b4;
     char *p=NULL,*next=NULL;
     int i,len,plen;
     
     while (!current->text[0]) {
-	if (!fgets (line, LINE_LEN, fd)) return NULL;
+	if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
 	//TODO: it seems that format of time is not easily determined, it may be 1:12, 1:12.0 or 0:1:12.0
 	//to describe the same moment in time. Maybe there are even more formats in use.
 	//if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8)
@@ -516,9 +539,13 @@
 	}
 			current->lines=i+1;
     }
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
+sub_styles_t *sub_styles = NULL;
+
 subtitle *sub_read_line_ssa(FILE *fd,subtitle *current) {
 /*
  * Sub Station Alpha v4 (and v2?) scripts have 9 commas before subtitle
@@ -530,30 +557,74 @@
  * http://www.eswat.demon.co.uk is where the SSA specs can be found
  */
         int comma;
-        static int max_comma = 32; /* let's use 32 for the case that the */
-                    /*  amount of commas increase with newer SSA versions */
+        static int max_comma = 9;
 
 	int hour1, min1, sec1, hunsec1,
 	    hour2, min2, sec2, hunsec2, nothing;
-	int num;
+	int num, style_alignment, font_size, font_bold, font_italic;
 	
-	char line[LINE_LEN+1],
-	     line3[LINE_LEN+1],
+	char line[SUB_LINE_LENGTH+1],
+	     line3[SUB_LINE_LENGTH+1],
+	     line4[SUB_LINE_LENGTH+1],
+	     style_font_name[SUB_LINE_LENGTH - 6],
 	     *line2;
 	char *tmp;
 
+	sub_styles_t *ss_tmp1, *ss_tmp2;
+
+	current->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;
 	do {
-		if (!fgets (line, LINE_LEN, fd)) return NULL;
+		if (!fgets (line, SUB_LINE_LENGTH, fd)) return NULL;
+		if (sscanf(line, "Style: %[^,],%[^,],%d,%*d,%*d,%*d,%*d,%d,%d,%*d,%*d,%*d,%d,%*d,%*d,%*d,%*d,%*d", line4, style_font_name,
+			&font_size, &font_bold, &font_italic, &style_alignment) == 6) {
+		    ss_tmp1 = (sub_styles_t *) calloc(sizeof(sub_styles_t), 1);
+		    ss_tmp1->next = NULL;
+		    sub_ssa_alignment(0, style_alignment, &(ss_tmp1->alignment)); // 0: SSA original layout
+		    ss_tmp1->style_name = (char *)malloc(strlen(line4) + 1);
+		    strcpy(ss_tmp1->style_name, line4);
+		    ss_tmp1->font_name = (char *)malloc(strlen(style_font_name) + 1);
+		    strcpy(ss_tmp1->font_name, style_font_name);
+		    ss_tmp1->font_point_size = font_size;
+		    ss_tmp1->font_slant = (font_italic == 0) ? 'r' : 'i';
+		    ss_tmp1->font_weight = (font_bold == 0) ? 'm' : 'b';
+		    {
+			sprintf(line4, "%s-%d%s%s", ss_tmp1->font_name, ss_tmp1->font_point_size, (font_italic == 0) ? "" : ":italic",
+			    (font_bold == 0) ? "" : ":bold");
+			ss_tmp1->font_string = strdup(line4);
+		    }
+		    if (sub_styles == NULL) {
+			// this is the first style
+			sub_styles = ss_tmp1;
+		    } else if (sub_styles->style_name == NULL){
+			// this is the first style, but some other informations (currently SSA version) have already inserted
+			ss_tmp1->ass = sub_styles->ass;
+			free(sub_styles);
+			sub_styles = ss_tmp1;
+		    } else {
+			// this is not the first style
+			ss_tmp2 = sub_styles;
+			while (ss_tmp2->next != NULL) ss_tmp2 = ss_tmp2->next;
+			ss_tmp2->next = ss_tmp1;
+		    }
+		} else if (strncmp(line, "ScriptType: v4.00+", 18) == 0) {
+		    if (!sub_styles) sub_styles = (sub_styles_t *) calloc(sizeof(sub_styles_t), 1);
+		    sub_styles->ass = 1;
+		} else if (strncmp(line, "PlayResY:", 9) == 0) {
+		    sscanf(&line[9], "%d", &num);
+		    if (!sub_styles) sub_styles = (sub_styles_t *) calloc(sizeof(sub_styles_t), 1);
+		    sub_styles->yresolution = num;
+printf("\nPRY %d\n", sub_styles->yresolution);
+		}
 	} while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,"
-			"%[^\n\r]", &nothing,
+			"%[^,\n\r]%[^\n\r]", &nothing,
 			&hour1, &min1, &sec1, &hunsec1, 
-			&hour2, &min2, &sec2, &hunsec2,
+			&hour2, &min2, &sec2, &hunsec2, line4,
 			line3) < 9
 		 &&
 		 sscanf (line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,"
-			 "%[^\n\r]", &nothing,
+			 "%[^,\n\r]%[^\n\r]", &nothing,
 			 &hour1, &min1, &sec1, &hunsec1, 
-			 &hour2, &min2, &sec2, &hunsec2,
+			 &hour2, &min2, &sec2, &hunsec2, line4,
 			 line3) < 9	    );
 
         line2=strchr(line3, ',');
@@ -562,8 +633,6 @@
           {
             tmp = line2;
             if(!(tmp=strchr(++tmp, ','))) break;
-            if(*(++tmp) == ' ') break; 
-                  /* a space after a comma means we're already in a sentence */
             line2 = tmp;
           }
 
@@ -573,8 +642,20 @@
 
 	current->lines=0;num=0;
 	current->start = 360000*hour1 + 6000*min1 + 100*sec1 + hunsec1;
-	current->end   = 360000*hour2 + 6000*min2 + 100*sec2 + hunsec2;
+	current->end   = 360000*hour2 + 6000*min2 + 100*sec2 + hunsec2;	
+	for (ss_tmp1 = sub_styles ; ss_tmp1 != NULL ; ss_tmp1 = ss_tmp1->next) {
+	    if (strcmp(ss_tmp1->style_name, line4) == 0 || strcmp(ss_tmp1->style_name, &line4[1]) == 0) {
+		current->alignment = ss_tmp1->alignment;
+		current->font_string = ss_tmp1->font_string;
+		current->font_point_size = ss_tmp1->font_point_size;
+		break;
+	    }
+	}
 	
+	current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+	current->text_style[0]->alignment = current->alignment;
+	current->text_style[0]->font_string = current->font_string;
+	current->text_style[0]->font_point_size = current->font_point_size;
         while (((tmp=strstr(line2, "\\n")) != NULL) || ((tmp=strstr(line2, "\\N")) != NULL) ){
 		current->text[num]=(char *)malloc(tmp-line2+1);
 		strncpy (current->text[num], line2, tmp-line2);
@@ -583,6 +664,7 @@
 		num++;
 		current->lines++;
 		if (current->lines >=  SUB_MAX_TEXT) return current;
+		current->text_style[current->lines] = NULL;
 	}
 
 	current->text[num]=strdup(line2);
@@ -592,14 +674,46 @@
 }
 
 void sub_pp_ssa(subtitle *sub) {
-	int l=sub->lines;
+	int l=sub->lines, alignment_number;
 	char *so,*de,*start;
+	char *position;
+	text_style_t *previous_line_style = NULL;
 
+printf("\nPRY %d\n", sub_styles->yresolution);
 	while (l){
-            	/* eliminate any text enclosed with {}, they are font and color settings */
+            	/* eliminate any unsupported settings enclosed with {}. currently supporting only positioning and alignment (\pos, \a and \an commands) */
             	so=de=sub->text[--l];
             	while (*so) {
             		if(*so == '{' && so[1]=='\\') {
+			    for (position = &(so[1]) ; *position != '}' ; ++position) {
+				if (*position == '\\') {
+				    if (strncmp("\\pos", position, 4) == 0) {
+					if (!sub->text_style[l]) {
+					    sub->text_style[l] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+					}
+					sub->text_style[l]->alignment = SUB_ALIGNMENT_POSITIONAL;
+					sscanf(position, "\\pos(%d,%d", &(sub->text_style[l]->posx), &(sub->text_style[l]->posy));
+printf("\n pre: %d (%f/%f)\n", sub->text_style[l]->posy, (float) disp_h, (float) sub_styles->yresolution);
+					sub->text_style[l]->posy = (int) ((float)sub->text_style[l]->posy * (float) disp_h / (float) sub_styles->yresolution);
+printf(" post: %d\n", sub->text_style[l]->posy);
+					previous_line_style = sub->text_style[l];
+				    } else if (sscanf(position, "\\an%d", &alignment_number) == 1) {
+					if (!sub->text_style[l]) {
+					    sub->text_style[l] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+					    sub->text_style[l]->alignment = '\0';
+					}
+					sub_ssa_alignment(1, alignment_number, &(sub->text_style[l]->alignment)); // numpad layout
+					previous_line_style = sub->text_style[l];
+				    } else if (sscanf(position, "\\a%d", &alignment_number) == 1) {
+					if (!sub->text_style[l]) {
+					    sub->text_style[l] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+					    sub->text_style[l]->alignment = '\0';
+					}
+					sub_ssa_alignment((sub_styles) ? sub_styles->ass : 0, alignment_number, &sub->text_style[l]->alignment);
+					previous_line_style = sub->text_style[l];
+				    }
+				}
+			    }
             			for (start=so; *so && *so!='}'; so++);
             			if(*so) so++; else so=start;
             		}
@@ -607,6 +721,10 @@
             			*de=*so;
             			so++; de++;
             		}
+		    if (sub->text_style[l] == NULL && previous_line_style != NULL) {
+			 sub->text_style[l] = (text_style_t*) malloc(sizeof(text_style_t)); // no need to use calloc(3)
+			 memcpy(sub->text_style[l], previous_line_style, sizeof(text_style_t)); // this copies also the reference to font_name
+		    }
             	}
             	*de=*so;
         }
@@ -621,10 +739,10 @@
  * by set, based on code by szabi (dunnowhat sub format ;-)
  */
 subtitle *sub_read_line_pjs(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
-    char text[LINE_LEN+1], *s, *d;
+    char line[SUB_LINE_LENGTH+1];
+    char text[SUB_LINE_LENGTH+1], *s, *d;
 
-    if (!fgets (line, LINE_LEN, fd))
+    if (!fgets (line, SUB_LINE_LENGTH, fd))
 	return NULL;
     /* skip spaces */
     for (s=line; *s && isspace(*s); s++);
@@ -655,18 +773,20 @@
     current->text[0] = strdup(text);
     current->lines = 1;
 
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
 subtitle *sub_read_line_mpsub(FILE *fd, subtitle *current) {
-	char line[LINE_LEN+1];
+	char line[SUB_LINE_LENGTH+1];
 	float a,b;
 	int num=0;
 	char *p, *q;
 
 	do
 	{
-		if (!fgets(line, LINE_LEN, fd)) return NULL;
+		if (!fgets(line, SUB_LINE_LENGTH, fd)) return NULL;
 	} while (sscanf (line, "%f %f", &a, &b) !=2);
 
 	mpsub_position += a*mpsub_multiplier; 
@@ -674,8 +794,10 @@
 	mpsub_position += b*mpsub_multiplier; 
 	current->end=(int) mpsub_position;
 
+	current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+	current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
 	while (num < SUB_MAX_TEXT) {
-		if (!fgets (line, LINE_LEN, fd)) {
+		if (!fgets (line, SUB_LINE_LENGTH, fd)) {
 			if (num == 0) return NULL;
 			else return current;
 		}
@@ -704,13 +826,13 @@
 #endif
 
 subtitle *sub_read_line_aqt(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     char *next;
     int i;
 
     while (1) {
     // try to locate next subtitle
-        if (!fgets (line, LINE_LEN, fd))
+        if (!fgets (line, SUB_LINE_LENGTH, fd))
 		return NULL;
         if (!(sscanf (line, "-->> %ld", &(current->start)) <1))
 		break;
@@ -725,14 +847,14 @@
     previous_aqt_sub = current;
 #endif
 
-    if (!fgets (line, LINE_LEN, fd))
+    if (!fgets (line, SUB_LINE_LENGTH, fd))
 	return NULL;
 
     sub_readtext((char *) &line,&current->text[0]);
     current->lines = 1;
     current->end = current->start; // will be corrected by next subtitle
 
-    if (!fgets (line, LINE_LEN, fd))
+    if (!fgets (line, SUB_LINE_LENGTH, fd))
 	return current;
 
     next = line,i=1;
@@ -753,6 +875,8 @@
 	return NULL;
 	}
 
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
@@ -761,14 +885,14 @@
 #endif
 
 subtitle *sub_read_line_subrip09(FILE *fd,subtitle *current) {
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     int a1,a2,a3;
     char * next=NULL;
     int i,len;
    
     while (1) {
     // try to locate next subtitle
-        if (!fgets (line, LINE_LEN, fd))
+        if (!fgets (line, SUB_LINE_LENGTH, fd))
 		return NULL;
         if (!((len=sscanf (line, "[%d:%d:%d]",&a1,&a2,&a3)) < 3))
 		break;
@@ -785,7 +909,7 @@
     previous_subrip09_sub = current;
 #endif
 
-    if (!fgets (line, LINE_LEN, fd))
+    if (!fgets (line, SUB_LINE_LENGTH, fd))
 	return NULL;
 
     next = line,i=0;
@@ -809,22 +933,25 @@
 	return NULL;
 	}
 
+    current->text_style[0] = (text_style_t*) calloc(sizeof(text_style_t), 1);
+    current->text_style[0]->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;;
     return current;
 }
 
 subtitle *sub_read_line_jacosub(FILE * fd, subtitle * current)
 {
-    char line1[LINE_LEN], line2[LINE_LEN], directive[LINE_LEN], *p, *q;
+    char line1[SUB_LINE_LENGTH], line2[SUB_LINE_LENGTH], directive[SUB_LINE_LENGTH], *p, *q;
     unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0;
     static unsigned jacoTimeres = 30;
     static int jacoShift = 0;
 
     memset(current, 0, sizeof(subtitle));
-    memset(line1, 0, LINE_LEN);
-    memset(line2, 0, LINE_LEN);
-    memset(directive, 0, LINE_LEN);
+    memset(line1, 0, SUB_LINE_LENGTH);
+    memset(line2, 0, SUB_LINE_LENGTH);
+    memset(directive, 0, SUB_LINE_LENGTH);
+    current->alignment = SUB_ALIGNMENT_PVBOTTOM|SUB_ALIGNMENT_PHCENTER|SUB_ALIGNMENT_BCENTER;
     while (!current->text[0]) {
-	if (!fgets(line1, LINE_LEN, fd)) {
+	if (!fgets(line1, SUB_LINE_LENGTH, fd)) {
 	    return NULL;
 	}
 	if (sscanf
@@ -922,11 +1049,33 @@
 		continue;
 	    }
 	    if (strstr(directive, "JL") != NULL) {
-		current->alignment = SUB_ALIGNMENT_BOTTOMLEFT;
-	    } else if (strstr(directive, "JR") != NULL) {
-		current->alignment = SUB_ALIGNMENT_BOTTOMRIGHT;
+		current->alignment = SUB_ALIGNMENT_BLEFT;
+		if (strstr(directive, "JBC") != NULL)
+		    current->alignment |= SUB_ALIGNMENT_PHCENTER;
+		else if (strstr(directive, "JBR") != NULL)
+		    current->alignment |= SUB_ALIGNMENT_PHRIGHT;
+		else current->alignment |= SUB_ALIGNMENT_PHLEFT;
+ 	    } else if (strstr(directive, "JR") != NULL) {
+		current->alignment = SUB_ALIGNMENT_BRIGHT;
+		if (strstr(directive, "JBC") != NULL)
+		    current->alignment |= SUB_ALIGNMENT_PHCENTER;
+		else if (strstr(directive, "JBL") != NULL)
+		    current->alignment |= SUB_ALIGNMENT_PHLEFT;
+		else current->alignment |= SUB_ALIGNMENT_PHRIGHT;
 	    } else {
-		current->alignment = SUB_ALIGNMENT_BOTTOMCENTER;
+		current->alignment = SUB_ALIGNMENT_BCENTER;
+		if (strstr(directive, "JBL") != NULL)
+		    current->alignment |= SUB_ALIGNMENT_PHLEFT;
+		else if (strstr(directive, "JBR") != NULL)
+		    current->alignment |= SUB_ALIGNMENT_PHRIGHT;
+		else current->alignment |= SUB_ALIGNMENT_PHCENTER;
+	    }
+	    if (strstr(directive, "VT") != NULL) {
+		current->alignment |= SUB_ALIGNMENT_PVTOP;
+	    } else if (strstr(directive, "VM") != NULL) {
+		current->alignment |= SUB_ALIGNMENT_PVMIDDLE;
+ 	    } else {
+		current->alignment |= SUB_ALIGNMENT_PVBOTTOM;
 	    }
 	    strcpy(line2, line1);
 	    p = line2;
@@ -963,6 +1112,10 @@
 		if (*(p + 1) == 'n') {
 		    *q = '\0';
 		    q = line1;
+		    if (current->lines == 0) {
+			current->text_style[0] = (text_style_t*)calloc(sizeof(text_style_t),1);
+			current->text_style[0]->alignment = current->alignment;
+		    } else current->text_style[current->lines] = NULL;
 		    current->text[current->lines++] = strdup(line1);
 		    ++p;
 		    break;
@@ -982,11 +1135,11 @@
 		    (*(p + 1) == '~') || (*(p + 1) == '{')) {
 		    ++p;
 		} else if (eol(*(p + 1))) {
-		    if (!fgets(directive, LINE_LEN, fd))
+		    if (!fgets(directive, SUB_LINE_LENGTH, fd))
 			return NULL;
 		    trail_space(directive);
 		    strncat(line2, directive,
-			    (LINE_LEN > 511) ? LINE_LEN : 511);
+			    (SUB_LINE_LENGTH > 511) ? SUB_LINE_LENGTH : 511);
 		    break;
 		}
 	    default:
@@ -998,19 +1151,23 @@
 	}			//-- for
 	*q = '\0';
 	current->text[current->lines] = strdup(line1);
+	if (current->lines == 0) {
+	    current->text_style[0] = (text_style_t*)calloc(sizeof(text_style_t),1);
+	    current->text_style[0]->alignment = current->alignment;
+	} else current->text_style[current->lines] = NULL;
     }				//-- while
     current->lines++;
     return current;
 }
 
 int sub_autodetect (FILE *fd, int *uses_time) {
-    char line[LINE_LEN+1];
+    char line[SUB_LINE_LENGTH+1];
     int i,j=0;
     char p;
     
     while (j < 100) {
 	j++;
-	if (!fgets (line, LINE_LEN, fd))
+	if (!fgets (line, SUB_LINE_LENGTH, fd))
 	    return SUB_INVALID;
 
 	if (sscanf (line, "{%d}{%d}", &i, &i)==2)
@@ -1130,14 +1287,16 @@
 
 		if (iconv(icdsc, &ip, &ileft,
 			  &op, &oleft) == (size_t)(-1)) {
-			mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: error recoding line (1).\n");
-			l++;
-			break;
+//			mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: error recoding line (1).\n");
+//			l++;
+//			break;
+			continue;
 		}
 		if (!(ot = (char *)malloc(op - icbuffer + 1))){
 			mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: error allocating mem.\n");
 			l++;
-		   	break;
+//		   	break;
+		   	continue;
 		}
 		*op='\0' ;
 		strcpy (ot, icbuffer);
@@ -1184,7 +1343,7 @@
 #endif
 subtitle* sub_fribidi (subtitle *sub, int sub_utf8)
 {
-  FriBidiChar logical[LINE_LEN+1], visual[LINE_LEN+1]; // Hopefully these two won't smash the stack
+  FriBidiChar logical[SUB_LINE_LENGTH+1], visual[SUB_LINE_LENGTH+1]; // Hopefully these two won't smash the stack
   char        *ip      = NULL, *op     = NULL;
   FriBidiCharType base;
   size_t len,orig_len;
@@ -1203,8 +1362,8 @@
   while (l) {
     ip = sub->text[--l];
     orig_len = len = strlen( ip ); // We assume that we don't use full unicode, only UTF-8 or ISO8859-x
-    if(len > LINE_LEN) {
-      mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: sub->text is longer than LINE_LEN.\n");
+    if(len > SUB_LINE_LENGTH) {
+      mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: sub->text is longer than SUB_LINE_LENGTH.\n");
       l++;
       break;
     }
@@ -1341,7 +1500,7 @@
 }
 #endif
 
-sub_data* sub_read_file (char *filename, float fps) {
+sub_data* sub_read_file (char *filename, float fps, int v_width, int v_height) {
         //filename is assumed to be malloc'ed,  free() is used in sub_free()
     FILE *fd;
     int n_max, n_first, i, j, sub_first, sub_orig;
@@ -1370,6 +1529,8 @@
     if(filename==NULL) return NULL; //qnx segfault
     fd=fopen (filename, "r"); if (!fd) return NULL;
     
+    disp_w = v_width;
+    disp_h = v_height;
     sub_format=sub_autodetect (fd, &uses_time);
     mpsub_multiplier = (uses_time ? 100.0 : 1.0);
     if (sub_format==SUB_INVALID) {mp_msg(MSGT_SUBREADER,MSGL_WARN,"SUB: Could not determine file format\n");return NULL;}
@@ -1396,7 +1557,7 @@
 #endif
 
     sub_num=0;n_max=32;
-    first=(subtitle *)malloc(n_max*sizeof(subtitle));
+    first=(subtitle *)calloc(sizeof(subtitle), n_max);
     if(!first){
 #ifdef USE_ICONV
 	  subcp_close();
@@ -1446,6 +1607,7 @@
 	    first[sub_num].alignment = sub->alignment;
   	    for(i = 0; i < sub->lines; ++i){
 		first[sub_num].text[i] = sub->text[i];
+		first[sub_num].text_style[i] = sub->text_style[i];
   	    }
 	    if (previous_sub_end){
   		first[sub_num - 1].end = previous_sub_end;
@@ -1459,6 +1621,7 @@
 		first[j + 1].alignment = first[j].alignment;
     		for(i = 0; i < first[j].lines; ++i){
       		    first[j + 1].text[i] = first[j].text[i];
+      		    first[j + 1].text_style[i] = first[j].text_style[i];
 		}
 		if(!j || (first[j - 1].start <= sub->start)){
 	    	    first[j].start = sub->start;
@@ -1467,6 +1630,7 @@
 	    	    first[j].alignment = sub->alignment;
 	    	    for(i = 0; i < SUB_MAX_TEXT; ++i){
 			first[j].text[i] = sub->text[i];
+			first[j].text_style[i] = sub->text_style[i];
 		    }
 		    if (previous_sub_end){
 			first[j].end = first[j - 1].end;
@@ -1642,8 +1806,7 @@
 		    break;
 	    }
 	    if (higher_line >= SUB_MAX_TEXT) {
-		// the 'block' has too much lines, so we don't overlap the
-		// subtitles
+		// the 'block' has too many lines, so we don't overlap their subtitles
 		second = (subtitle *) realloc(second, (sub_num + sub_to_add + 1) * sizeof(subtitle));
 		for (j = 0; j <= sub_to_add; ++j) {
 		    int ls;
@@ -1653,6 +1816,12 @@
 		    second[sub_num + j].lines = first[sub_first + j].lines;
 		    second[sub_num + j].alignment = first[sub_first + j].alignment;
 		    for (ls = 0; ls < second[sub_num + j].lines; ls++) {
+			if (first[sub_first + j].text_style[ls] == NULL)
+			    second[sub_num + j].text_style[ls] = NULL;
+			else {
+			    second[sub_num + j].text_style[ls] = (text_style_t *) malloc(sizeof(text_style_t)); // no need to use calloc(3)
+			    memcpy(second[sub_num + j].text_style[ls], first[sub_first + j].text_style[ls], sizeof(text_style_t));
+			}
 			second[sub_num + j].text[ls] = strdup(first[sub_first + j].text[ls]);
 		    }
 		}
@@ -1674,10 +1843,18 @@
 		if (placeholder[counter][j] != -1) {
 		    int lines = first[placeholder[counter][j]].lines;
 		    for (ls = 0; ls < lines; ++ls) {
+			if (first[placeholder[counter][j]].text_style[ls] == NULL)
+			    second[sub_num].text_style[i] = NULL;
+			else {
+			    second[sub_num].text_style[i] = (text_style_t *) malloc(sizeof(text_style_t)); // no need to use calloc(3)
+			    memcpy(second[sub_num].text_style[i], first[placeholder[counter][j]].text_style[ls], sizeof(text_style_t));
+			}
 			second[sub_num].text[i++] = strdup(first[placeholder[counter][j]].text[ls]);
 		    }
 		    j += lines - 1;
 		} else {
+		    second[sub_num].text_style[i] = (text_style_t *) calloc(sizeof(text_style_t), 1);
+		    second[sub_num].text_style[i]->alignment = SUB_ALIGNMENT_FAKE;
 		    second[sub_num].text[i++] = strdup(" ");
 		}
 	    }
@@ -1699,6 +1876,9 @@
     for (j = sub_orig - 1; j >= 0; --j) {
 	for (i = first[j].lines - 1; i >= 0; --i) {
 	    free(first[j].text[i]);
+	    if (first[j].text_style[i]) {
+		free (first[j].text_style[i]);
+	    }
 	}
     }
     free(first);
@@ -1715,6 +1895,18 @@
     subt_data->sub_num = sub_num;
     subt_data->sub_errs = sub_errs;
     subt_data->subtitles = return_sub;
+
+    /* free memory allocated for sub styles */
+    if (sub_styles != NULL) {
+	sub_styles_t *ss_tmp;
+	do {
+	    ss_tmp = sub_styles;
+	    sub_styles = ss_tmp->next;
+	    free(ss_tmp->style_name);
+	    free(ss_tmp);
+	} while (sub_styles != NULL);
+    }
+
     return subt_data;
 }
 
@@ -2263,6 +2455,63 @@
     free( subd );
 }
 
+void sub_ssa_alignment(char numpad_layout, int alignment_number, unsigned char *alignment)
+{
+    switch (alignment_number) {	// numpad layout
+    case 1:
+	*alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVBOTTOM; // bottom left
+	break;
+    case 2:
+	*alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHCENTER | SUB_ALIGNMENT_PVBOTTOM; // bottom center
+	break;
+    case 3:
+	*alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHRIGHT | SUB_ALIGNMENT_PVBOTTOM; // bottom right
+	break;
+    case 4:
+	if (numpad_layout)
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVMIDDLE; // middle left
+	else
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVTOP; // top left
+	break;
+    case 5:
+	if (numpad_layout)
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHCENTER | SUB_ALIGNMENT_PVMIDDLE; // middle center
+	else
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVTOP; // top left
+	break;
+    case 6:
+	if (numpad_layout)
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHRIGHT | SUB_ALIGNMENT_PVMIDDLE; // middle right
+	else
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHCENTER | SUB_ALIGNMENT_PVTOP; // top center
+	break;
+    case 7:
+	if (numpad_layout)
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVTOP; // top left
+	else
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHRIGHT | SUB_ALIGNMENT_PVTOP; // top right
+	break;
+    case 8:
+	if (numpad_layout)
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHCENTER | SUB_ALIGNMENT_PVTOP; // top center
+	else
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVTOP; // top left
+	break;
+    case 9:
+	if (numpad_layout)
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHRIGHT | SUB_ALIGNMENT_PVTOP; // top right
+	else
+	    *alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHLEFT | SUB_ALIGNMENT_PVMIDDLE; // middle left
+	break;
+    case 10:
+	*alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHCENTER | SUB_ALIGNMENT_PVMIDDLE; // middle center
+	break;
+    case 11:
+	*alignment = SUB_ALIGNMENT_BCENTER | SUB_ALIGNMENT_PHRIGHT | SUB_ALIGNMENT_PVMIDDLE; // middle right
+	break;
+    }
+}
+
 #ifdef DUMPSUBS
 int main(int argc, char **argv) {  // for testing
     sub_data *subd;
diff -Nur -x '*.o' -x '0*' -x 'conf*' -x 'codec*' -x '*.a' -x '*depend' -x '*.so' -x 'pci*' MPlayer-20050307/subreader.h MPlayer-20050307.patch/subreader.h
--- MPlayer-20050307/subreader.h	2004-10-18 22:41:05.000000000 +0200
+++ MPlayer-20050307.patch/subreader.h	2005-03-29 00:08:06.000000000 +0200
@@ -3,6 +3,7 @@
 
 #include <stdio.h>
 
+extern char *font_name;
 extern int suboverlap_enabled;
 extern int sub_no_text_pp;  // disable text post-processing
 extern int sub_match_fuzziness;
@@ -29,16 +30,32 @@
 
 #define MAX_SUBTITLE_FILES 128
 
+/* Maximal length of line of a subtitle */
+#define SUB_LINE_LENGTH 1000
+
 #define SUB_MAX_TEXT 10
-#define SUB_ALIGNMENT_BOTTOMLEFT       1
-#define SUB_ALIGNMENT_BOTTOMCENTER     2
-#define SUB_ALIGNMENT_BOTTOMRIGHT      3
-#define SUB_ALIGNMENT_MIDDLELEFT       4
-#define SUB_ALIGNMENT_MIDDLECENTER     5
-#define SUB_ALIGNMENT_MIDDLERIGHT      6
-#define SUB_ALIGNMENT_TOPLEFT          7
-#define SUB_ALIGNMENT_TOPCENTER        8
-#define SUB_ALIGNMENT_TOPRIGHT         9
+#define SUB_ALIGNMENT_BLOCK		0x30 // block alignment mask
+#define SUB_ALIGNMENT_HORIZONTAL	0x03 // horizontal alignment mask
+#define SUB_ALIGNMENT_VERTICAL		0x0C // vertical alignment mask
+#define SUB_ALIGNMENT_POSITIONAL	0x40 // alignment is position-based
+#define SUB_ALIGNMENT_FAKE		0xFF // this is a fake subtitle, used in overlapping subs
+#define SUB_ALIGNMENT_PHLEFT	0x2
+#define SUB_ALIGNMENT_PHCENTER	0x3
+#define SUB_ALIGNMENT_PHRIGHT	0x1
+#define SUB_ALIGNMENT_PVTOP	0x8
+#define SUB_ALIGNMENT_PVMIDDLE	0xC
+#define SUB_ALIGNMENT_PVBOTTOM	0x4
+#define SUB_ALIGNMENT_BLEFT     0x20
+#define SUB_ALIGNMENT_BCENTER   0x30
+#define SUB_ALIGNMENT_BRIGHT    0x10
+#define SUB_ALIGNMENT_BJUSTIFY  0x00
+
+typedef struct {
+    char alignment;
+    char *font_string;
+    int  posx, posy;
+    int font_point_size;
+} text_style_t;
 
 typedef struct {
 
@@ -48,7 +65,11 @@
     unsigned long end;
     
     char *text[SUB_MAX_TEXT];
+    text_style_t *text_style[SUB_MAX_TEXT];
+
     unsigned char alignment;
+    char *font_string;
+    int font_point_size;
 } subtitle;
 
 typedef struct {
@@ -59,13 +80,32 @@
     int sub_errs;
 } sub_data;
 
+/// this struct is used to store style informations in complex sub formats (ssa/ass, jacosub)
+typedef struct sub_styles sub_styles_t;
+struct sub_styles {
+    char *style_name;
+    char *font_name;
+    int font_point_size;
+    char font_slant; // 'r' or '\0' roman, 'i' italic, 'o' oblique
+    char font_weight; // 'l' light, 'm' or '\0' medium, 'd' demibold, 'b' bold, 'k' black
+    char *font_string;
+    unsigned char alignment;
+
+    char ass; // 0 this is a SSA (V4.00), 1 this is a ASS (V4.00+)
+    int  yresolution; // scale all the y positions against this value
+		      // (for SSA/ASS and absolute positioning)
+
+    sub_styles_t *next;
+};
+//~
+
 #ifdef  USE_FRIBIDI
 extern char *fribidi_charset;
 extern int flip_hebrew;
 extern int fribidi_flip_commas;
 #endif
 
-sub_data* sub_read_file (char *filename, float pts);
+sub_data* sub_read_file (char *filename, float pts, int video_width, int video_height);
 subtitle* subcp_recode1 (subtitle *sub);
 // enca_fd is the file enca uses to determine the codepage.
 // setting to NULL disables enca.
@@ -74,6 +114,7 @@
 #ifdef HAVE_ENCA
 void* guess_cp(FILE *enca_fd, char *preferred_language, char *fallback);
 #endif
+void sub_ssa_alignment(char numpad_layout, int alignment_number, unsigned char *alignment);
 char ** sub_filenames(char *path, char *fname);
 void list_sub_file(sub_data* subd);
 void dump_srt(sub_data* subd, float fps);


More information about the MPlayer-dev-eng mailing list