📄 sub.c
字号:
#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include "config.h"#ifdef HAVE_MALLOC_H#include <uclib.h>#endif#ifdef USE_DVDNAV#include "stream/stream.h"#include "stream/stream_dvdnav.h"#define OSD_NAV_BOX_ALPHA 0x7f#endif#ifdef HAVE_TV_TELETEXT#include "stream/tv.h"#include "osdep/timer.h"#endif#include "mplayer.h"#include "mp_msg.h"#include "help_mp.h"#include "video_out.h"#include "font_load.h"#include "sub.h"#include "spudec.h"#include "libavutil/common.h"#define NEW_SPLITTING// 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 subtitlesstruct 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;};//^char * sub_osd_names[]={ MSGTR_VO_SUB_Seekbar, MSGTR_VO_SUB_Play, MSGTR_VO_SUB_Pause, MSGTR_VO_SUB_Stop, MSGTR_VO_SUB_Rewind, MSGTR_VO_SUB_Forward, MSGTR_VO_SUB_Clock, MSGTR_VO_SUB_Contrast, MSGTR_VO_SUB_Saturation, MSGTR_VO_SUB_Volume, MSGTR_VO_SUB_Brightness, MSGTR_VO_SUB_Hue, MSGTR_VO_SUB_Balance};char * sub_osd_names_short[] ={ "", "|>", "||", "[]", "<<" , ">>", "", "", "", "", "", "", "" };//static int vo_font_loaded=-1;font_desc_t* vo_font=NULL;font_desc_t* sub_font=NULL;unsigned char* vo_osd_text=NULL;#ifdef HAVE_TV_TELETEXTvoid* vo_osd_teletext_page=NULL;int vo_osd_teletext_half = 0;int vo_osd_teletext_mode=0;int vo_osd_teletext_format=0;int vo_osd_teletext_scale=0;#endifint sub_unicode=0;int sub_utf8=0;int sub_pos=100;int sub_width_p=100;int sub_alignment=2; /* 0=top, 1=center, 2=bottom */int sub_visibility=1;int sub_bg_color=0; /* subtitles background color */int sub_bg_alpha=0;int sub_justify=0;#ifdef USE_DVDNAVstatic nav_highlight_t nav_hl;#endif// 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;}// renders char to a big per-object buffer where alpha and bitmap are separatedstatic void draw_alpha_buf(mp_osd_obj_t* obj, int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ 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; 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", 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++, as++) { if (*b < *bs) *b = *bs; if (*as) { if (*a == 0 || *a > *as) *a = *as; } } b+= dstskip; a+= dstskip; bs+= srcskip; as+= srcskip; }}// allocates/enlarges the alpha/bitmap bufferstatic void alloc_buf(mp_osd_obj_t* obj){ int len; if (obj->bbox.x2 < obj->bbox.x1) obj->bbox.x2 = obj->bbox.x1; if (obj->bbox.y2 < obj->bbox.y1) obj->bbox.y2 = obj->bbox.y1; obj->stride = ((obj->bbox.x2-obj->bbox.x1)+7)&(~7); len = obj->stride*(obj->bbox.y2-obj->bbox.y1); if (obj->allocated<len) { obj->allocated = len; free(obj->bitmap_buffer); free(obj->alpha_buffer); obj->bitmap_buffer = (unsigned char *)memalign(32, len); obj->alpha_buffer = (unsigned char *)memalign(32, len); } memset(obj->bitmap_buffer, sub_bg_color, len); memset(obj->alpha_buffer, sub_bg_alpha, len);}// renders the bufferinline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){ if (obj->allocated > 0) { draw_alpha(obj->bbox.x1,obj->bbox.y1, obj->bbox.x2-obj->bbox.x1, obj->bbox.y2-obj->bbox.y1, obj->bitmap_buffer, obj->alpha_buffer, obj->stride); }}unsigned utf8_get_char(const char **str) { const uint8_t *strp = (const uint8_t *)*str; unsigned c; GET_UTF8(c, *strp++, goto no_utf8;); *str = (const char *)strp; return c;no_utf8: strp = (const uint8_t *)*str; c = *strp++; *str = (const char *)strp; return c;}inline static void vo_update_text_osd(mp_osd_obj_t* obj,int dxs,int dys){ const char *cp=vo_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; alloc_buf(obj); cp=vo_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; }}#ifdef USE_DVDNAVvoid osd_set_nav_box (uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey) { nav_hl.sx = sx; nav_hl.sy = sy; nav_hl.ex = ex; nav_hl.ey = ey;}inline static void vo_update_nav (mp_osd_obj_t *obj, int dxs, int dys) { int len; obj->bbox.x1 = obj->x = nav_hl.sx; obj->bbox.y1 = obj->y = nav_hl.sy; obj->bbox.x2 = nav_hl.ex; obj->bbox.y2 = nav_hl.ey; alloc_buf (obj); len = obj->stride * (obj->bbox.y2 - obj->bbox.y1); memset (obj->bitmap_buffer, OSD_NAV_BOX_ALPHA, len); memset (obj->alpha_buffer, OSD_NAV_BOX_ALPHA, len); obj->flags |= OSDFLAG_BBOX | OSDFLAG_CHANGED; if (obj->bbox.y2 > obj->bbox.y1 && obj->bbox.x2 > obj->bbox.x1) obj->flags |= OSDFLAG_VISIBLE;}#endif#ifdef HAVE_TV_TELETEXT// renders char to a big per-object buffer where alpha and bitmap are separatedstatic 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; }}inline static void vo_update_text_teletext(mp_osd_obj_t *obj, int dxs, int dys){ 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; unsigned char colors[8]={1,85,150,226,70,105,179,254}; unsigned char* buf[9]; 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); //very simple teletext font auto scaling if(!vo_osd_teletext_scale && hm*(max_rows+1)>dys){ text_font_scale_factor*=1.0*(dys)/((max_rows+1)*hm); force_load_font=1; vo_osd_teletext_scale=text_font_scale_factor; obj->flags&=~OSDFLAG_VISIBLE; return; } 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; 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 characterTODO: support for separated graphics symbols (where six rectangles does not touch each other) +--+ +--+ 87654321 |01| |12| -------- |10| <= |34| <= 00100110 <= 0x26 |01| |56| +--+ +--+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -