📄 sub.c
字号:
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; 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; } y+=sub_font->height; } } }inline static void vo_update_spudec_sub(mp_osd_obj_t* obj, int dxs, int dys){ unsigned int bbox[4]; spudec_calc_bbox(vo_spudec, dxs, dys, bbox); obj->bbox.x1 = bbox[0]; obj->bbox.x2 = bbox[1]; obj->bbox.y1 = bbox[2]; obj->bbox.y2 = bbox[3]; obj->flags |= OSDFLAG_BBOX;}inline static void vo_draw_spudec_sub(mp_osd_obj_t* obj, void (*draw_alpha)(int x0, int y0, int w, int h, unsigned char* src, unsigned char* srca, int stride)){ spudec_draw_scaled(vo_spudec, obj->dxs, obj->dys, draw_alpha);}void *vo_spudec=NULL;void *vo_vobsub=NULL;static int draw_alpha_init_flag=0;extern void vo_draw_alpha_init(void); mp_osd_obj_t* vo_osd_list=NULL;static mp_osd_obj_t* new_osd_obj(int type){ mp_osd_obj_t* osd=malloc(sizeof(mp_osd_obj_t)); memset(osd,0,sizeof(mp_osd_obj_t)); osd->next=vo_osd_list; vo_osd_list=osd; osd->type=type; osd->alpha_buffer = NULL; osd->bitmap_buffer = NULL; osd->allocated = -1; return osd;}void free_osd_list(void){ mp_osd_obj_t* obj=vo_osd_list; while(obj){ mp_osd_obj_t* next=obj->next; if (obj->alpha_buffer) free(obj->alpha_buffer); if (obj->bitmap_buffer) free(obj->bitmap_buffer); free(obj); obj=next; } vo_osd_list=NULL;}#define FONT_LOAD_DEFER 6int vo_update_osd(int dxs,int dys){ mp_osd_obj_t* obj=vo_osd_list; int chg=0;#ifdef HAVE_FREETYPE static int defer_counter = 0, prev_dxs = 0, prev_dys = 0;#endif#ifdef HAVE_FREETYPE // here is the right place to get screen dimensions if (((dxs != vo_image_width) && (subtitle_autoscale == 2 || subtitle_autoscale == 3)) || ((dys != vo_image_height) && (subtitle_autoscale == 1 || subtitle_autoscale == 3))) { // screen dimensions changed // wait a while to avoid useless reloading of the font if (dxs == prev_dxs || dys == prev_dys) { defer_counter++; } else { prev_dxs = dxs; prev_dys = dys; defer_counter = 0; } if (defer_counter >= FONT_LOAD_DEFER) force_load_font = 1; } if (force_load_font) { force_load_font = 0; load_font_ft(dxs, dys, &vo_font, font_name); if (sub_font_name) load_font_ft(dxs, dys, &sub_font, sub_font_name); else sub_font = vo_font; prev_dxs = dxs; prev_dys = dys; defer_counter = 0; } else { if (!vo_font) load_font_ft(dxs, dys, &vo_font, font_name); if (!sub_font) { if (sub_font_name) load_font_ft(dxs, dys, &sub_font, sub_font_name); else sub_font = vo_font; } }#endif while(obj){ if(dxs!=obj->dxs || dys!=obj->dys || obj->flags&OSDFLAG_FORCE_UPDATE){ int vis=obj->flags&OSDFLAG_VISIBLE; obj->flags&=~OSDFLAG_BBOX; switch(obj->type){#ifdef USE_DVDNAV case OSDTYPE_DVDNAV: vo_update_nav(obj,dxs,dys); break;#endif case OSDTYPE_SUBTITLE: vo_update_text_sub(obj,dxs,dys); break;#ifdef HAVE_TV_TELETEXT case OSDTYPE_TELETEXT: vo_update_text_teletext(obj,dxs,dys); break;#endif case OSDTYPE_PROGBAR: vo_update_text_progbar(obj,dxs,dys); break; case OSDTYPE_SPU: if(sub_visibility && vo_spudec && spudec_visible(vo_spudec)){ vo_update_spudec_sub(obj, dxs, dys); obj->flags|=OSDFLAG_VISIBLE|OSDFLAG_CHANGED; } else obj->flags&=~OSDFLAG_VISIBLE; break; case OSDTYPE_OSD: if(vo_font && vo_osd_text && vo_osd_text[0]){ vo_update_text_osd(obj,dxs,dys); // update bbox obj->flags|=OSDFLAG_VISIBLE|OSDFLAG_CHANGED; } else obj->flags&=~OSDFLAG_VISIBLE; break; } // check bbox: if(!(obj->flags&OSDFLAG_BBOX)){ // we don't know, so assume the whole screen changed :( obj->bbox.x1=obj->bbox.y1=0; obj->bbox.x2=dxs; obj->bbox.y2=dys; obj->flags|=OSDFLAG_BBOX; } else { // check bbox, reduce it if it's out of bounds (corners): if(obj->bbox.x1<0) obj->bbox.x1=0; if(obj->bbox.y1<0) obj->bbox.y1=0; if(obj->bbox.x2>dxs) obj->bbox.x2=dxs; if(obj->bbox.y2>dys) obj->bbox.y2=dys; if(obj->flags&OSDFLAG_VISIBLE) // debug: mp_msg(MSGT_OSD,MSGL_DBG2,"OSD update: %d;%d %dx%d \n", obj->bbox.x1,obj->bbox.y1,obj->bbox.x2-obj->bbox.x1, obj->bbox.y2-obj->bbox.y1); } // check if visibility changed: if(vis != (obj->flags&OSDFLAG_VISIBLE) ) obj->flags|=OSDFLAG_CHANGED; // remove the cause of automatic update: obj->dxs=dxs; obj->dys=dys; obj->flags&=~OSDFLAG_FORCE_UPDATE; } if(obj->flags&OSDFLAG_CHANGED){ chg|=1<<obj->type; mp_msg(MSGT_OSD,MSGL_DBG2,"OSD chg: %d V: %s pb:%d \n",obj->type,(obj->flags&OSDFLAG_VISIBLE)?"yes":"no",vo_osd_progbar_type); } obj=obj->next; } return chg;}void vo_init_osd(void){ if(!draw_alpha_init_flag){ draw_alpha_init_flag=1; vo_draw_alpha_init(); } if(vo_osd_list) free_osd_list(); // temp hack, should be moved to mplayer/mencoder later new_osd_obj(OSDTYPE_OSD); new_osd_obj(OSDTYPE_SUBTITLE); new_osd_obj(OSDTYPE_PROGBAR); new_osd_obj(OSDTYPE_SPU);#ifdef USE_DVDNAV new_osd_obj(OSDTYPE_DVDNAV);#endif#if HAVE_TV_TELETEXT new_osd_obj(OSDTYPE_TELETEXT);#endif#ifdef HAVE_FREETYPE force_load_font = 1;#endif}int vo_osd_changed_flag=0;void vo_remove_text(int dxs,int dys,void (*remove)(int x0,int y0, int w,int h)){ mp_osd_obj_t* obj=vo_osd_list; vo_update_osd(dxs,dys); while(obj){ if(((obj->flags&OSDFLAG_CHANGED) || (obj->flags&OSDFLAG_VISIBLE)) && (obj->flags&OSDFLAG_OLD_BBOX)){ int w=obj->old_bbox.x2-obj->old_bbox.x1; int h=obj->old_bbox.y2-obj->old_bbox.y1; if(w>0 && h>0){ vo_osd_changed_flag=obj->flags&OSDFLAG_CHANGED; // temp hack remove(obj->old_bbox.x1,obj->old_bbox.y1,w,h); }// obj->flags&=~OSDFLAG_OLD_BBOX; } obj=obj->next; }}void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){ mp_osd_obj_t* obj=vo_osd_list; vo_update_osd(dxs,dys); while(obj){ if(obj->flags&OSDFLAG_VISIBLE){ vo_osd_changed_flag=obj->flags&OSDFLAG_CHANGED; // temp hack switch(obj->type){ case OSDTYPE_SPU: vo_draw_spudec_sub(obj, draw_alpha); // FIXME break;#ifdef USE_DVDNAV case OSDTYPE_DVDNAV:#endif#ifdef HAVE_TV_TELETEXT case OSDTYPE_TELETEXT:#endif case OSDTYPE_OSD: case OSDTYPE_SUBTITLE: case OSDTYPE_PROGBAR: vo_draw_text_from_buffer(obj,draw_alpha); break; } obj->old_bbox=obj->bbox; obj->flags|=OSDFLAG_OLD_BBOX; } obj->flags&=~OSDFLAG_CHANGED; obj=obj->next; }}static int vo_osd_changed_status = 0;int vo_osd_changed(int new_value){ mp_osd_obj_t* obj=vo_osd_list; int ret = vo_osd_changed_status; vo_osd_changed_status = new_value; while(obj){ if(obj->type==new_value) obj->flags|=OSDFLAG_FORCE_UPDATE; obj=obj->next; } return ret;}// BBBBBBBBBBBB AAAAAAAAAAAAA BBBBBBBBBBB// BBBBBBBBBBBB BBBBBBBBBBBBB// BBBBBBB// return TRUE if we have osd in the specified rectangular area:int vo_osd_check_range_update(int x1,int y1,int x2,int y2){ mp_osd_obj_t* obj=vo_osd_list; while(obj){ if(obj->flags&OSDFLAG_VISIBLE){ if( (obj->bbox.x1<=x2 && obj->bbox.x2>=x1) && (obj->bbox.y1<=y2 && obj->bbox.y2>=y1) && obj->bbox.y2 > obj->bbox.y1 && obj->bbox.x2 > obj->bbox.x1 ) return 1; } obj=obj->next; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -