[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, ¤t->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]", ¬hing,
+ "%[^,\n\r]%[^\n\r]", ¬hing,
&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]", ¬hing,
+ "%[^,\n\r]%[^\n\r]", ¬hing,
&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,¤t->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