📄 freetype.c
字号:
vlc_value_t val; int i_scale = 1000; FT_BBox line; FT_BBox glyph_size; FT_Vector result; FT_Glyph tmp_glyph; /* Sanity check */ if( !p_region_in || !p_region_out ) return VLC_EGENERIC; psz_string = p_region_in->psz_text; if( !psz_string || !*psz_string ) return VLC_EGENERIC; if( VLC_SUCCESS == var_Get( p_filter, "scale", &val )) i_scale = val.i_int; if( p_region_in->p_style ) { i_font_color = __MAX( __MIN( p_region_in->p_style->i_font_color, 0xFFFFFF ), 0 ); i_font_alpha = __MAX( __MIN( p_region_in->p_style->i_font_alpha, 255 ), 0 ); i_font_size = __MAX( __MIN( p_region_in->p_style->i_font_size, 255 ), 0 ) * i_scale / 1000; } else { i_font_color = p_sys->i_font_color; i_font_alpha = 255 - p_sys->i_font_opacity; i_font_size = p_sys->i_default_font_size * i_scale / 1000; } if( i_font_color == 0xFFFFFF ) i_font_color = p_sys->i_font_color; if( !i_font_alpha ) i_font_alpha = 255 - p_sys->i_font_opacity; SetFontSize( p_filter, i_font_size ); i_red = ( i_font_color & 0x00FF0000 ) >> 16; i_green = ( i_font_color & 0x0000FF00 ) >> 8; i_blue = i_font_color & 0x000000FF; result.x = result.y = 0; line.xMin = line.xMax = line.yMin = line.yMax = 0; psz_unicode = psz_unicode_orig = malloc( ( strlen(psz_string) + 1 ) * sizeof(uint32_t) ); if( psz_unicode == NULL ) goto error;#if defined(WORDS_BIGENDIAN) iconv_handle = vlc_iconv_open( "UCS-4BE", "UTF-8" );#else iconv_handle = vlc_iconv_open( "UCS-4LE", "UTF-8" );#endif if( iconv_handle == (vlc_iconv_t)-1 ) { msg_Warn( p_filter, "unable to do conversion" ); goto error; } { char *p_out_buffer; const char *p_in_buffer = psz_string; size_t i_in_bytes, i_out_bytes, i_out_bytes_left, i_ret; i_in_bytes = strlen( psz_string ); i_out_bytes = i_in_bytes * sizeof( uint32_t ); i_out_bytes_left = i_out_bytes; p_out_buffer = (char *)psz_unicode; i_ret = vlc_iconv( iconv_handle, (const char**)&p_in_buffer, &i_in_bytes, &p_out_buffer, &i_out_bytes_left ); vlc_iconv_close( iconv_handle ); if( i_in_bytes ) { msg_Warn( p_filter, "failed to convert string to unicode (%m), " "bytes left %u", (unsigned)i_in_bytes ); goto error; } *(uint32_t*)p_out_buffer = 0; i_string_length = (i_out_bytes - i_out_bytes_left) / sizeof(uint32_t); }#if defined(HAVE_FRIBIDI) { uint32_t *p_fribidi_string; int32_t start_pos, pos = 0; p_fribidi_string = malloc( (i_string_length + 1) * sizeof(uint32_t) ); if( !p_fribidi_string ) goto error; /* Do bidi conversion line-by-line */ while( pos < i_string_length ) { while( pos < i_string_length ) { i_char = psz_unicode[pos]; if (i_char != '\r' && i_char != '\n') break; p_fribidi_string[pos] = i_char; ++pos; } start_pos = pos; while( pos < i_string_length ) { i_char = psz_unicode[pos]; if (i_char == '\r' || i_char == '\n') break; ++pos; } if (pos > start_pos) { FriBidiCharType base_dir = FRIBIDI_TYPE_LTR; fribidi_log2vis((FriBidiChar*)psz_unicode + start_pos, pos - start_pos, &base_dir, (FriBidiChar*)p_fribidi_string + start_pos, 0, 0, 0); } } free( psz_unicode_orig ); psz_unicode = psz_unicode_orig = p_fribidi_string; p_fribidi_string[ i_string_length ] = 0; }#endif /* Calculate relative glyph positions and a bounding box for the * entire string */ if( !(p_line = NewLine( strlen( psz_string ))) ) goto error; p_lines = p_line; i_pen_x = i_pen_y = 0; i_previous = i = 0; psz_line_start = psz_unicode;#define face p_sys->p_face#define glyph face->glyph while( *psz_unicode ) { i_char = *psz_unicode++; if( i_char == '\r' ) /* ignore CR chars wherever they may be */ { continue; } if( i_char == '\n' ) { psz_line_start = psz_unicode; if( !(p_next = NewLine( strlen( psz_string ))) ) goto error; p_line->p_next = p_next; p_line->i_width = line.xMax; p_line->i_height = face->size->metrics.height >> 6; p_line->pp_glyphs[ i ] = NULL; p_line->i_alpha = i_font_alpha; p_line->i_red = i_red; p_line->i_green = i_green; p_line->i_blue = i_blue; p_prev = p_line; p_line = p_next; result.x = __MAX( result.x, line.xMax ); result.y += face->size->metrics.height >> 6; i_pen_x = 0; i_previous = i = 0; line.xMin = line.xMax = line.yMin = line.yMax = 0; i_pen_y += face->size->metrics.height >> 6;#if 0 msg_Dbg( p_filter, "Creating new line, i is %d", i );#endif continue; } i_glyph_index = FT_Get_Char_Index( face, i_char ); if( p_sys->i_use_kerning && i_glyph_index && i_previous ) { FT_Vector delta; FT_Get_Kerning( face, i_previous, i_glyph_index, ft_kerning_default, &delta ); i_pen_x += delta.x >> 6; } p_line->p_glyph_pos[ i ].x = i_pen_x; p_line->p_glyph_pos[ i ].y = i_pen_y; i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_DEFAULT ); if( i_error ) { msg_Err( p_filter, "unable to render text FT_Load_Glyph returned" " %d", i_error ); goto error; } i_error = FT_Get_Glyph( glyph, &tmp_glyph ); if( i_error ) { msg_Err( p_filter, "unable to render text FT_Get_Glyph returned " "%d", i_error ); goto error; } FT_Glyph_Get_CBox( tmp_glyph, ft_glyph_bbox_pixels, &glyph_size ); i_error = FT_Glyph_To_Bitmap( &tmp_glyph, ft_render_mode_normal, 0, 1); if( i_error ) { FT_Done_Glyph( tmp_glyph ); continue; } p_line->pp_glyphs[ i ] = (FT_BitmapGlyph)tmp_glyph; /* Do rest */ line.xMax = p_line->p_glyph_pos[i].x + glyph_size.xMax - glyph_size.xMin + ((FT_BitmapGlyph)tmp_glyph)->left; if( line.xMax > (int)p_filter->fmt_out.video.i_visible_width - 20 ) { FT_Done_Glyph( (FT_Glyph)p_line->pp_glyphs[ i ] ); p_line->pp_glyphs[ i ] = NULL; FreeLine( p_line ); p_line = NewLine( strlen( psz_string )); if( p_prev ) p_prev->p_next = p_line; else p_lines = p_line; uint32_t *psz_unicode_saved = psz_unicode; while( psz_unicode > psz_line_start && *psz_unicode != ' ' ) { psz_unicode--; } if( psz_unicode == psz_line_start ) { /* try harder to break that line */ psz_unicode = psz_unicode_saved; while( psz_unicode > psz_line_start && *psz_unicode != '_' && *psz_unicode != '/' && *psz_unicode != '\\' && *psz_unicode != '.' ) { psz_unicode--; } } if( psz_unicode == psz_line_start ) { msg_Warn( p_filter, "unbreakable string" ); goto error; } else { *psz_unicode = '\n'; } psz_unicode = psz_line_start; i_pen_x = 0; i_previous = i = 0; line.xMin = line.xMax = line.yMin = line.yMax = 0; continue; } line.yMax = __MAX( line.yMax, glyph_size.yMax ); line.yMin = __MIN( line.yMin, glyph_size.yMin ); i_previous = i_glyph_index; i_pen_x += glyph->advance.x >> 6; i++; } p_line->i_width = line.xMax; p_line->i_height = face->size->metrics.height >> 6; p_line->pp_glyphs[ i ] = NULL; p_line->i_alpha = i_font_alpha; p_line->i_red = i_red; p_line->i_green = i_green; p_line->i_blue = i_blue; result.x = __MAX( result.x, line.xMax ); result.y += line.yMax - line.yMin;#undef face#undef glyph p_region_out->i_x = p_region_in->i_x; p_region_out->i_y = p_region_in->i_y; if( config_GetInt( p_filter, "freetype-yuvp" ) ) Render( p_filter, p_region_out, p_lines, result.x, result.y ); else RenderYUVA( p_filter, p_region_out, p_lines, result.x, result.y ); free( psz_unicode_orig ); FreeLines( p_lines ); return VLC_SUCCESS; error: free( psz_unicode_orig ); FreeLines( p_lines ); return VLC_EGENERIC;}#ifdef HAVE_FONTCONFIGstatic ft_style_t *CreateStyle( char *psz_fontname, int i_font_size, uint32_t i_font_color, uint32_t i_karaoke_bg_color, bool b_bold, bool b_italic, bool b_uline ){ ft_style_t *p_style = malloc( sizeof( ft_style_t )); if( p_style ) { p_style->i_font_size = i_font_size; p_style->i_font_color = i_font_color; p_style->i_karaoke_bg_color = i_karaoke_bg_color; p_style->b_italic = b_italic; p_style->b_bold = b_bold; p_style->b_underline = b_uline; p_style->psz_fontname = strdup( psz_fontname ); } return p_style;}static void DeleteStyle( ft_style_t *p_style ){ if( p_style ) { free( p_style->psz_fontname ); free( p_style ); }}static bool StyleEquals( ft_style_t *s1, ft_style_t *s2 ){ if( !s1 || !s2 ) return false; if( s1 == s2 ) return true; if(( s1->i_font_size == s2->i_font_size ) && ( s1->i_font_color == s2->i_font_color ) && ( s1->b_italic == s2->b_italic ) && ( s1->b_bold == s2->b_bold ) && ( s1->b_underline == s2->b_underline ) && ( !strcmp( s1->psz_fontname, s2->psz_fontname ))) { return true; } return false;}static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, uint32_t i_color, uint32_t i_karaoke_bg_color ){ font_stack_t *p_new; if( !p_font ) return VLC_EGENERIC; p_new = malloc( sizeof( font_stack_t ) ); if( ! p_new ) return VLC_ENOMEM; p_new->p_next = NULL; if( psz_name ) p_new->psz_name = strdup( psz_name ); else p_new->psz_name = NULL; p_new->i_size = i_size; p_new->i_color = i_color; p_new->i_karaoke_bg_color = i_karaoke_bg_color; if( !*p_font ) { *p_font = p_new; } else { font_stack_t *p_last; for( p_last = *p_font; p_last->p_next; p_last = p_last->p_next ) ; p_last->p_next = p_new; } return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -