summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
Diffstat (limited to 'sub')
-rw-r--r--sub/ass_mp.c15
-rw-r--r--sub/font_load.h7
-rw-r--r--sub/font_load_ft.c13
-rw-r--r--sub/osd_font.h2
-rw-r--r--sub/osd_ft.c969
-rw-r--r--sub/osd_libass.c375
-rw-r--r--sub/sub.c985
-rw-r--r--sub/sub.h40
-rw-r--r--sub/sub_cc.c2
-rw-r--r--sub/subreader.c2
10 files changed, 1440 insertions, 970 deletions
diff --git a/sub/ass_mp.c b/sub/ass_mp.c
index 88c55862f2..3dd743776d 100644
--- a/sub/ass_mp.c
+++ b/sub/ass_mp.c
@@ -34,22 +34,11 @@
#include "path.h"
#include "ass_mp.h"
#include "subreader.h"
+#include "sub/sub.h"
#include "stream/stream.h"
#include "options.h"
-#ifdef CONFIG_FONTCONFIG
-extern int font_fontconfig;
-#else
-static int font_fontconfig = -1;
-#endif
-extern char *font_name;
-extern char *sub_font_name;
-extern float text_font_scale_factor;
-extern int subtitle_autoscale;
-
-#ifdef CONFIG_ICONV
-extern char *sub_cp;
-#else
+#ifndef CONFIG_ICONV
static char *sub_cp = 0;
#endif
diff --git a/sub/font_load.h b/sub/font_load.h
index 7efe067aaf..933f84804f 100644
--- a/sub/font_load.h
+++ b/sub/font_load.h
@@ -83,13 +83,6 @@ typedef struct font_desc {
extern font_desc_t* vo_font;
-extern char *subtitle_font_encoding;
-extern float text_font_scale_factor;
-extern float osd_font_scale_factor;
-extern float subtitle_font_radius;
-extern float subtitle_font_thickness;
-extern int subtitle_autoscale;
-
extern int vo_image_width;
extern int vo_image_height;
diff --git a/sub/font_load_ft.c b/sub/font_load_ft.c
index eb6d70b657..9eb0ab50e8 100644
--- a/sub/font_load_ft.c
+++ b/sub/font_load_ft.c
@@ -48,23 +48,14 @@
#include "mp_msg.h"
#include "mplayer.h"
#include "path.h"
+#include "sub/sub.h"
+
#include "osd_font.h"
#if (FREETYPE_MAJOR > 2) || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 1)
#define HAVE_FREETYPE21
#endif
-char *subtitle_font_encoding = NULL;
-float text_font_scale_factor = 3.5;
-float osd_font_scale_factor = 4.0;
-float subtitle_font_radius = 2.0;
-float subtitle_font_thickness = 2.0;
-// 0 = no autoscale
-// 1 = video height
-// 2 = video width
-// 3 = diagonal
-int subtitle_autoscale = 3;
-
int vo_image_width = 0;
int vo_image_height = 0;
int force_load_font;
diff --git a/sub/osd_font.h b/sub/osd_font.h
index 6be45bc1fa..616c27d155 100644
--- a/sub/osd_font.h
+++ b/sub/osd_font.h
@@ -19,7 +19,7 @@
#ifndef MPLAYER_OSD_FONT_H
#define MPLAYER_OSD_FONT_H
-const unsigned char osd_font_pfb[] = {
+static const unsigned char osd_font_pfb[] = {
0x80,0x01,0x02,0x17,0x00,0x00,0x25,0x21,0x50,0x53,0x2d,0x41,0x64,0x6f,0x62,0x65,
0x46,0x6f,0x6e,0x74,0x2d,0x31,0x2e,0x30,0x3a,0x20,0x4f,0x53,0x44,0x20,0x31,0x2e,
0x30,0x30,0x0a,0x25,0x25,0x43,0x72,0x65,0x61,0x74,0x69,0x6f,0x6e,0x44,0x61,0x74,
diff --git a/sub/osd_ft.c b/sub/osd_ft.c
new file mode 100644
index 0000000000..f44100a3b9
--- /dev/null
+++ b/sub/osd_ft.c
@@ -0,0 +1,969 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "stream/stream.h"
+#include "stream/stream_dvdnav.h"
+#define OSD_NAV_BOX_ALPHA 0x7f
+
+#include "libmpcodecs/dec_teletext.h"
+#include "osdep/timer.h"
+
+#include "talloc.h"
+#include "mplayer.h"
+#include "path.h"
+#include "mp_msg.h"
+#include "libvo/video_out.h"
+#include "sub.h"
+#include "sub/font_load.h"
+#include "spudec.h"
+#include "libavutil/common.h"
+
+#define FONT_LOAD_DEFER 6
+#define NEW_SPLITTING
+
+//static int vo_font_loaded=-1;
+font_desc_t* vo_font=NULL;
+
+// Structures needed for the new splitting algorithm.
+// osd_text_t contains the single subtitle word.
+// osd_text_p is used to mark the lines of subtitles
+struct osd_text_t {
+ int osd_kerning, //kerning with the previous word
+ osd_length, //orizontal length inside the bbox
+ text_length, //number of characters
+ *text; //characters
+ struct osd_text_t *prev,
+ *next;
+};
+
+struct osd_text_p {
+ int value;
+ struct osd_text_t *ott;
+ struct osd_text_p *prev,
+ *next;
+};
+//^
+
+
+// return the real height of a char:
+static inline int get_height(int c,int h){
+ int font;
+ if ((font=vo_font->font[c])>=0)
+ if(h<vo_font->pic_a[font]->h) h=vo_font->pic_a[font]->h;
+ return h;
+}
+
+
+void vo_update_text_osd(struct osd_state *osd, mp_osd_obj_t *obj)
+{
+ const char *cp = osd->osd_text;
+ int x=20;
+ int h=0;
+ int font;
+
+ obj->bbox.x1=obj->x=x;
+ obj->bbox.y1=obj->y=10;
+
+ while (*cp){
+ uint16_t c=utf8_get_char(&cp);
+ render_one_glyph(vo_font, c);
+ x+=vo_font->width[c]+vo_font->charspace;
+ h=get_height(c,h);
+ }
+
+ obj->bbox.x2=x-vo_font->charspace;
+ obj->bbox.y2=obj->bbox.y1+h;
+ obj->flags|=OSDFLAG_BBOX;
+
+ osd_alloc_buf(obj);
+
+ cp = osd->osd_text;
+ x = obj->x;
+ while (*cp){
+ uint16_t c=utf8_get_char(&cp);
+ if ((font=vo_font->font[c])>=0)
+ draw_alpha_buf(obj,x,obj->y,
+ vo_font->width[c],
+ vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->w);
+ x+=vo_font->width[c]+vo_font->charspace;
+ }
+}
+
+static int vo_osd_teletext_scale=0;
+
+// renders char to a big per-object buffer where alpha and bitmap are separated
+static void tt_draw_alpha_buf(mp_osd_obj_t* obj, int x0,int y0, int w,int h, unsigned char* src, int stride,int fg,int bg,int alpha)
+{
+ int dststride = obj->stride;
+ int dstskip = obj->stride-w;
+ int srcskip = stride-w;
+ int i, j;
+ unsigned char *b = obj->bitmap_buffer + (y0-obj->bbox.y1)*dststride + (x0-obj->bbox.x1);
+ unsigned char *a = obj->alpha_buffer + (y0-obj->bbox.y1)*dststride + (x0-obj->bbox.x1);
+ unsigned char *bs = src;
+ if (x0 < obj->bbox.x1 || x0+w > obj->bbox.x2 || y0 < obj->bbox.y1 || y0+h > obj->bbox.y2) {
+ mp_msg(MSGT_OSD,MSGL_ERR,"tt 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;
+ }
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++, b++, a++, bs++) {
+ *b=(fg-bg)*(*bs)/255+bg;
+ *a=alpha;
+ }
+ b+= dstskip;
+ a+= dstskip;
+ bs+= srcskip;
+ }
+}
+void vo_update_text_teletext(struct osd_state *osd, mp_osd_obj_t *obj)
+{
+ int h=0,w=0,i,j,font,flashon;
+ int wm,hm;
+ int color;
+ int x,y,x0,y0;
+ int cols,rows;
+ int wm12;
+ int hm13;
+ int hm23;
+ int start_row,max_rows;
+ int b,ax[6],ay[6],aw[6],ah[6];
+ tt_char tc;
+ tt_char* tdp=vo_osd_teletext_page;
+ static const uint8_t colors[8]={1,85,150,226,70,105,179,254};
+ unsigned char* buf[9];
+ int dxs = osd->w, dys = osd->h;
+
+ obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
+ if (!tdp || !vo_osd_teletext_mode) {
+ obj->flags&=~OSDFLAG_VISIBLE;
+ return;
+ }
+ flashon=(GetTimer()/1000000)%2;
+ switch(vo_osd_teletext_half){
+ case TT_ZOOM_TOP_HALF:
+ start_row=0;
+ max_rows=VBI_ROWS/2;
+ break;
+ case TT_ZOOM_BOTTOM_HALF:
+ start_row=VBI_ROWS/2;
+ max_rows=VBI_ROWS/2;
+ break;
+ default:
+ start_row=0;
+ max_rows=VBI_ROWS;
+ break;
+ }
+ wm=0;
+ for(i=start_row;i<max_rows;i++){
+ for(j=0;j<VBI_COLUMNS;j++){
+ tc=tdp[i*VBI_COLUMNS+j];
+ if(!tc.ctl && !tc.gfx)
+ {
+ render_one_glyph(vo_font, tc.unicode);
+ if (wm<vo_font->width[tc.unicode])
+ wm=vo_font->width[tc.unicode];
+ }
+ }
+ }
+
+ hm=vo_font->height+1;
+ wm=dxs*hm*max_rows/(dys*VBI_COLUMNS);
+
+#ifdef CONFIG_FREETYPE
+ //very simple teletext font auto scaling
+ if(!vo_osd_teletext_scale && hm*(max_rows+1)>dys){
+ osd_font_scale_factor*=1.0*(dys)/((max_rows+1)*hm);
+ force_load_font=1;
+ vo_osd_teletext_scale=osd_font_scale_factor;
+ obj->flags&=~OSDFLAG_VISIBLE;
+ return;
+ }
+#endif
+
+ cols=dxs/wm;
+ rows=dys/hm;
+
+ if(cols>VBI_COLUMNS)
+ cols=VBI_COLUMNS;
+ if(rows>max_rows)
+ rows=max_rows;
+ w=cols*wm-vo_font->charspace;
+ h=rows*hm-vo_font->charspace;
+
+ if(w<dxs)
+ x0=(dxs-w)/2;
+ else
+ x0=0;
+ if(h<dys)
+ y0=(dys-h)/2;
+ else
+ y0=0;
+
+ wm12=wm>>1;
+ hm13=(hm+1)/3;
+ hm23=hm13<<1;
+
+ for(i=0;i<6;i+=2){
+ ax[i+0]=0;
+ aw[i+0]=wm12;
+
+ ax[i+1]=wm12;
+ aw[i+1]=wm-wm12;
+ }
+
+ for(i=0;i<2;i++){
+ ay[i+0]=0;
+ ah[i+0]=hm13;
+
+ ay[i+2]=hm13;
+ ah[i+2]=hm-hm23;
+
+ ay[i+4]=hm-hm13;
+ ah[i+4]=hm13;
+ }
+
+ obj->x = 0;
+ obj->y = 0;
+ obj->bbox.x1 = x0;
+ obj->bbox.y1 = y0;
+ obj->bbox.x2 = x0+w;
+ obj->bbox.y2 = y0+h;
+ obj->flags |= OSDFLAG_BBOX;
+ osd_alloc_buf(obj);
+
+ for(i=0;i<9;i++)
+ buf[i]=malloc(wm*hm);
+
+ //alpha
+ if(vo_osd_teletext_format==TT_FORMAT_OPAQUE ||vo_osd_teletext_format==TT_FORMAT_OPAQUE_INV)
+ color=1;
+ else
+ color=200;
+ memset(buf[8],color,wm*hm);
+ //colors
+ if(vo_osd_teletext_format==TT_FORMAT_OPAQUE ||vo_osd_teletext_format==TT_FORMAT_TRANSPARENT){
+ for(i=0;i<8;i++){
+ memset(buf[i],(unsigned char)(1.0*(255-color)*colors[i]/255),wm*hm);
+ }
+ }else{
+ for(i=0;i<8;i++)
+ memset(buf[i],(unsigned char)(1.0*(255-color)*colors[7-i]/255),wm*hm);
+ }
+
+ y=y0;
+ for(i=0;i<rows;i++){
+ x=x0;
+ for(j=0;j<cols;j++){
+ tc=tdp[(i+start_row)*VBI_COLUMNS+j];
+ if (tc.hidden) { x+=wm; continue;}
+ if(!tc.gfx || (tc.flh && !flashon)){
+ /* Rendering one text character */
+ draw_alpha_buf(obj,x,y,wm,hm,buf[tc.bg],buf[8],wm);
+ if(tc.unicode!=0x20 && tc.unicode!=0x00 && !tc.ctl &&
+ (!tc.flh || flashon) &&
+ (font=vo_font->font[tc.unicode])>=0 && y+hm<dys){
+ tt_draw_alpha_buf(obj,x,y,vo_font->width[tc.unicode],vo_font->height,
+ vo_font->pic_b[font]->bmp+vo_font->start[tc.unicode]-vo_font->charspace*vo_font->pic_a[font]->w,
+ vo_font->pic_b[font]->w,
+ buf[tc.fg][0],buf[tc.bg][0],buf[8][0]);
+ }
+ }else{
+/*
+Rendering one graphics character
+TODO: support for separated graphics symbols (where six rectangles does not touch each other)
+
+ +--+ +--+ 87654321
+ |01| |12| --------
+ |10| <= |34| <= 00100110 <= 0x26
+ |01| |56|
+ +--+ +--+
+
+(0:wm/2) (wm/2:wm-wm/2)
+
+********** *********** (0:hm/3)
+*** **** **** ****
+*** 1 **** **** 2 ****
+*** **** **** ****
+********** ***********
+********** ***********
+
+********** *********** (hm/3:hm-2*hm/3)
+********** ***********
+*** **** **** ****
+*** 3 **** **** 4 ****
+*** **** **** ****
+********** ***********
+********** ***********
+********** ***********
+
+********** *********** (hm-hm/3:hm/3)
+*** **** **** ****
+*** 5 **** **** 6 ****
+*** **** **** ****
+********** ***********
+********** ***********
+
+*/
+ if(tc.gfx>1){ //separated gfx
+ for(b=0;b<6;b++){
+ color=(tc.unicode>>b)&1?tc.fg:tc.bg;
+ draw_alpha_buf(obj,x+ax[b]+1,y+ay[b]+1,aw[b]-2,ah[b]-2,buf[color],buf[8],wm);
+ }
+ //separated gfx (background borders)
+ //vertical
+ draw_alpha_buf(obj,x ,y,1,hm,buf[tc.bg],buf[8],wm);
+ draw_alpha_buf(obj,x+ax[1]-1,y,2,hm,buf[tc.bg],buf[8],wm);
+ draw_alpha_buf(obj,x+ax[1]+aw[1]-1,y,wm-ax[1]-aw[1]+1,hm,buf[tc.bg],buf[8],wm);
+ //horizontal
+ draw_alpha_buf(obj,x,y ,wm,1,buf[tc.bg],buf[8],wm);
+ draw_alpha_buf(obj,x,y+ay[0]+ah[0]-1,wm,2,buf[tc.bg],buf[8],wm);
+ draw_alpha_buf(obj,x,y+ay[2]+ah[2]-1,wm,2,buf[tc.bg],buf[8],wm);
+ draw_alpha_buf(obj,x,y+ay[4]+ah[4]-1,wm,hm-ay[4]-ah[4]+1,buf[tc.bg],buf[8],wm);
+ }else{
+ for(b=0;b<6;b++){
+ color=(tc.unicode>>b)&1?tc.fg:tc.bg;
+ draw_alpha_buf(obj,x+ax[b],y+ay[b],aw[b],ah[b],buf[color],buf[8],wm);
+ }
+ }
+ }
+ x+=wm;
+ }
+ y+=hm;
+ }
+ for(i=0;i<9;i++)
+ free(buf[i]);
+}
+
+// if we have n=256 bars then OSD progbar looks like below
+//
+// 0 1 2 3 ... 256 <= vo_osd_progbar_value
+// | | | | |
+// [ === === === ... === ]
+//
+// the above schema is rescalled to n=elems bars
+
+void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t *obj){
+
+ obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
+
+ if(vo_osd_progbar_type<0 || !vo_font){
+ obj->flags&=~OSDFLAG_VISIBLE;
+ return;
+ }
+
+ render_one_glyph(vo_font, OSD_PB_START);
+ render_one_glyph(vo_font, OSD_PB_END);
+ render_one_glyph(vo_font, OSD_PB_0);
+ render_one_glyph(vo_font, OSD_PB_1);
+ render_one_glyph(vo_font, vo_osd_progbar_type);
+
+ // calculate bbox corners:
+ { int h=0;
+ int y=(osd->h-vo_font->height)/2;
+ int delimw=vo_font->width[OSD_PB_START]
+ +vo_font->width[OSD_PB_END]
+ +vo_font->charspace;
+ int width=(2*osd->w-3*delimw)/3;
+ int charw=vo_font->width[OSD_PB_0]+vo_font->charspace;
+ int elems=width/charw;
+ int x=(osd->w-elems*charw-delimw)/2;
+ int delta = 0;
+ h=get_height(OSD_PB_START,h);
+ h=get_height(OSD_PB_END,h);
+ h=get_height(OSD_PB_0,h);
+ h=get_height(OSD_PB_1,h);
+ if (vo_osd_progbar_type>0 && vo_font->font[vo_osd_progbar_type]>=0){
+ delta = vo_font->width[vo_osd_progbar_type]+vo_font->spacewidth;
+ delta = (x-delta > 0) ? delta : x;
+ h=get_height(vo_osd_progbar_type,h);
+ }
+ obj->bbox.x1=obj->x=x;
+ obj->bbox.y1=obj->y=y;
+ obj->bbox.x2=x+width+delimw;
+ obj->bbox.y2=y+h; //vo_font->height;
+ obj->flags|=OSDFLAG_BBOX;
+ obj->params.progbar.elems=elems;
+ obj->bbox.x1-=delta; // space for an icon
+ }
+
+ osd_alloc_buf(obj);
+
+ {
+ int minw = vo_font->width[OSD_PB_START]+vo_font->width[OSD_PB_END]+vo_font->width[OSD_PB_0];
+ if (vo_osd_progbar_type>0 && vo_font->font[vo_osd_progbar_type]>=0){
+ minw += vo_font->width[vo_osd_progbar_type]+vo_font->charspace+vo_font->spacewidth;
+ }
+ if (obj->bbox.x2 - obj->bbox.x1 < minw) return; // space too small, don't render anything
+ }
+
+ // render it:
+ { unsigned char *s;
+ unsigned char *sa;
+ int i,w,h,st,mark;
+ int x=obj->x;
+ int y=obj->y;
+ int c,font;
+ int charw=vo_font->width[OSD_PB_0]+vo_font->charspace;
+ int elems=obj->params.progbar.elems;
+
+ if (vo_osd_progbar_value<=0)
+ mark=0;
+ else {
+ int ev=vo_osd_progbar_value*elems;
+ mark=ev>>8;
+ if (ev & 0xFF) mark++;
+ if (mark>elems) mark=elems;
+ }
+
+
+// printf("osd.progbar width=%d xpos=%d\n",width,x);
+
+ c=vo_osd_progbar_type;
+ if(vo_osd_progbar_type>0 && (font=vo_font->font[c])>=0) {
+ int xp=x-vo_font->width[c]-vo_font->spacewidth;
+ draw_alpha_buf(obj,(xp<0?0:xp),y,
+ vo_font->width[c],
+ vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->w);
+ }
+
+ c=OSD_PB_START;
+ if ((font=vo_font->font[c])>=0)
+ draw_alpha_buf(obj,x,y,
+ vo_font->width[c],
+ vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->w);
+ x+=vo_font->width[c]+vo_font->charspace;
+
+ c=OSD_PB_0;
+ if ((font=vo_font->font[c])>=0){
+ w=vo_font->width[c];
+ h=vo_font->pic_a[font]->h;
+ s=vo_font->pic_b[font]->bmp+vo_font->start[c];
+ sa=vo_font->pic_a[font]->bmp+vo_font->start[c];
+ st=vo_font->pic_a[font]->w;
+ if ((i=mark)) do {
+ draw_alpha_buf(obj,x,y,w,h,s,sa,st);
+ x+=charw;
+ } while(--i);
+ }
+
+ c=OSD_PB_1;
+ if ((font=vo_font->font[c])>=0){
+ w=vo_font->width[c];
+ h=vo_font->pic_a[font]->h;
+ s =vo_font->pic_b[font]->bmp+vo_font->start[c];
+ sa=vo_font->pic_a[font]->bmp+vo_font->start[c];
+ st=vo_font->pic_a[font]->w;
+ if ((i=elems-mark)) do {
+ draw_alpha_buf(obj,x,y,w,h,s,sa,st);
+ x+=charw;
+ } while(--i);
+ }
+
+ c=OSD_PB_END;
+ if ((font=vo_font->font[c])>=0)
+ draw_alpha_buf(obj,x,y,
+ vo_font->width[c],
+ vo_font->pic_a[font]->h,
+ vo_font->pic_b[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->bmp+vo_font->start[c],
+ vo_font->pic_a[font]->w);
+// x+=vo_font->width[c]+vo_font->charspace;
+
+ }
+// vo_osd_progbar_value=(vo_osd_progbar_value+1)&0xFF;
+
+}
+
+void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t *obj){
+ unsigned char *t;
+ int c,i,j,l,x,y,font,prevc,counter;
+ int k;
+ int xsize;
+ int dxs = osd->w, dys = osd->h;
+ int xmin=dxs,xmax=0;
+ int h,lasth;
+ int xtblc, utblc;
+ struct font_desc *sub_font = osd->sub_font;
+
+ obj->flags|=OSDFLAG_CHANGED|OSDFLAG_VISIBLE;
+
+ if(!vo_sub || !osd->sub_font || !sub_visibility || (sub_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=sub_font->height;
+ l=vo_sub->lines;
+
+ {
+ struct osd_text_t *osl, *cp_ott, *tmp_ott, *tmp;
+ struct osd_text_p *otp_sub = NULL, *otp_sub_tmp = NULL, // 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 = -sub_font->charspace;
+ l--;
+ t=vo_sub->text[i++];
+ char_position = 0;
+ char_seq = calloc(strlen(t), sizeof(int));
+
+ prevc = -1;
+
+ otp = NULL;
+ osl = NULL;
+ x = 1;
+
+ // reading the subtitle words from vo_sub->text[]
+ while (*t) {
+ if (sub_utf8)
+ c = utf8_get_char((const char **)&t);
+ else if ((c = *t++) >= 0x80 && sub_unicode)
+ c = (c<<8) + *t++;
+ if (k==MAX_UCS){
+ t += strlen(t); // end here
+ mp_msg(MSGT_OSD,MSGL_WARN,"\nMAX_UCS exceeded!\n");
+ }
+ if (!c) c++; // avoid UCS 0
+ render_one_glyph(sub_font, c);
+
+ if (c == ' ') {
+ struct osd_text_t *tmp_ott = 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 =
+ sub_font->charspace + sub_font->width[' '];
+ cp_ott = tmp_ott;
+ }
+ tmp_ott->osd_length = xsize;
+ tmp_ott->text_length = char_position;
+ tmp_ott->text = 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 = sub_font->width[c] + sub_font->charspace + kerning(sub_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 = sub_font->font[c]) >= 0)) {
+ if (sub_font->pic_a[font]->h > h) {
+ h = sub_font->pic_a[font]->h;
+ }
+ }
+ } else {
+ if (x) {
+ mp_msg(MSGT_OSD, MSGL_WARN, "\nSubtitle word '%s' too long!\n", t);
+ x = 0;
+ }
+ }
+ }
+ }// for len (all words from subtitle line read)
+
+ // osl holds an ordered (as they appear in the lines) chain of the subtitle words
+ {
+ struct osd_text_t *tmp_ott = 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 =
+ sub_font->charspace + sub_font->width[' '];
+ cp_ott = tmp_ott;
+ }
+ tmp_ott->osd_length = xsize;
+ tmp_ott->text_length = char_position;
+ tmp_ott->text = malloc(char_position * sizeof(int));
+ for (counter = 0; counter < char_position; ++counter)
+ tmp_ott->text[counter] = char_seq[counter];
+ char_position = 0;
+ xsize = -sub_font->charspace;
+ }
+ free(char_seq);
+
+ 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 = 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 = 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 * sub_font->charspace - sub_font->width[' '];
+ } else {
+ tmp_otp->value = value;
+ exit = 1;
+ }
+ }
+
+
+#ifdef NEW_SPLITTING
+ // minimum holds the 'sum of the differences in length among the lines',
+ // a measure of the evenness of the lengths 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 length 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);
+ 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
+
+ // write lines into utbl
+ xtblc = 0;
+ utblc = 0;
+ obj->y = dys;
+ obj->params.subtitle.lines = 0;
+ for (tmp_otp = otp_sub; tmp_otp != NULL; tmp_otp = tmp_otp->next) {
+
+ if ((obj->params.subtitle.lines++) >= MAX_UCSLINES)
+ break;
+
+ if (h > obj->y) { // out of the screen so end parsing
+ obj->y -= lasth - sub_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(sub_font, c);
+ obj->params.subtitle.utbl[utblc++] = c;
+ k++;
+ }
+ obj->params.subtitle.utbl[utblc++] = ' ';
+ }
+ obj->params.subtitle.utbl[utblc - 1] = 0;
+ obj->y -= sub_font->height;
+ }
+ if(obj->params.subtitle.lines)
+ obj->y = dys - ((obj->params.subtitle.lines - 1) * sub_font->height + sub_font->pic_a[sub_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;
+ }
+ free(tmp->text);
+ free(tmp);
+
+ for(pmt = otp_sub; pmt->next != NULL; free(pmt->prev)) {
+ pmt = pmt->next;
+ }
+ free(pmt);
+ }
+
+ }
+ /// 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*sub_font->height;
+ obj->flags|=OSDFLAG_BBOX;
+
+ osd_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];
+ }
+ prevc = -1;
+ while ((c=obj->params.subtitle.utbl[j++])){
+ x += kerning(sub_font,prevc,c);
+ if ((font=sub_font->font[c])>=0)
+ draw_alpha_buf(obj,x,y,
+ sub_font->width[c],
+ sub_font->pic_a[font]->h+y<obj->dys ? sub_font->pic_a[font]->h : obj->dys-y,
+ sub_font->pic_b[font]->bmp+sub_font->start[c],
+ sub_font->pic_a[font]->bmp+sub_font->start[c],
+ sub_font->pic_a[font]->w);
+ x+=sub_font->width[c]+sub_font->charspace;
+ prevc = c;