X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Ffreetype.c;h=e39d8afe595944438bc45bd81a4b3531480603ac;hb=cb6f956af387be6dd030caff8527f3238a7e3f54;hp=1aa10954eeb0d6f9be3d9421a19662f17c2aa9c6;hpb=01a57621cd22ef2c6f36ef3912e5c4400dd9c9ff;p=vlc diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index 1aa10954ee..e39d8afe59 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -43,9 +42,9 @@ #include #include -#include #include +#include #include FT_FREETYPE_H #include FT_GLYPH_H #define FT_FLOOR(X) ((X & -64) >> 6) @@ -94,7 +93,7 @@ static void Destroy( vlc_object_t * ); #ifdef HAVE_FONTCONFIG #define FONT_LONGTEXT N_("Font family for the font you want to use") #else -#define FONT_LONGTEXT N_("Fontfile for the font you want to use") +#define FONT_LONGTEXT N_("Font file for the font you want to use") #endif #define FONTSIZE_TEXT N_("Font size in pixels") @@ -114,7 +113,7 @@ static void Destroy( vlc_object_t * ); #define FONTSIZER_TEXT N_("Relative font size") #define FONTSIZER_LONGTEXT N_("This is the relative default size of the " \ "fonts that will be rendered on the video. If absolute font size is set, "\ - "relative size will be overriden." ) + "relative size will be overridden." ) static const int pi_sizes[] = { 20, 18, 16, 12, 6 }; static const char *const ppsz_sizes_text[] = { @@ -266,7 +265,7 @@ struct filter_sys_t int i_display_height; #ifdef HAVE_FONTCONFIG char* psz_fontfamily; - xml_t *p_xml; + xml_reader_t *p_xml; #endif input_attachment_t **pp_font_attachments; @@ -305,7 +304,7 @@ static int Create( vlc_object_t *p_this ) p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; - #ifdef HAVE_FONTCONFIG +#ifdef HAVE_FONTCONFIG p_sys->psz_fontfamily = NULL; p_sys->p_xml = NULL; #endif @@ -317,12 +316,12 @@ static int Create( vlc_object_t *p_this ) var_Create( p_filter, "freetype-rel-fontsize", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - psz_fontfamily = var_CreateGetString( p_filter, "freetype-font" ); - p_sys->i_default_font_size = var_CreateGetInteger( p_filter, "freetype-fontsize" ); - p_sys->i_effect = var_CreateGetInteger( p_filter, "freetype-effect" ); - p_sys->i_font_opacity = var_CreateGetInteger( p_filter,"freetype-opacity" ); + psz_fontfamily = var_InheritString( p_filter, "freetype-font" ); + p_sys->i_default_font_size = var_InheritInteger( p_filter, "freetype-fontsize" ); + p_sys->i_effect = var_InheritInteger( p_filter, "freetype-effect" ); + p_sys->i_font_opacity = var_InheritInteger( p_filter,"freetype-opacity" ); p_sys->i_font_opacity = __MAX( __MIN( p_sys->i_font_opacity, 255 ), 0 ); - p_sys->i_font_color = var_CreateGetInteger( p_filter, "freetype-color" ); + p_sys->i_font_color = var_InheritInteger( p_filter, "freetype-color" ); p_sys->i_font_color = __MAX( __MIN( p_sys->i_font_color , 0xFFFFFF ), 0 ); fontindex=0; @@ -346,55 +345,45 @@ static int Create( vlc_object_t *p_this ) } #ifdef HAVE_FONTCONFIG - /* Lets find some fontfile from freetype-font variable family */ - char *psz_fontsize; - if( asprintf( &psz_fontsize, "%d", p_sys->i_default_font_size ) == -1 ) - goto error; + msg_Dbg( p_filter, "Building font databases."); + mtime_t t1, t2; + t1 = mdate(); #ifdef WIN32 - dialog_progress_bar_t *p_dialog = dialog_ProgressCreate( p_filter, + dialog_progress_bar_t *p_dialog = NULL; + FcConfig *fcConfig = FcInitLoadConfig(); + + p_dialog = dialog_ProgressCreate( p_filter, _("Building font cache"), _("Please wait while your font cache is rebuilt.\n" - "This should take less than few minutes."), NULL ); - char *path = xmalloc( PATH_MAX + 1 ); - /* Fontconfig doesnt seem to know where windows fonts are with - * current contribs. So just tell default windows font directory - * is the place to search fonts - */ - GetWindowsDirectory( path, PATH_MAX + 1 ); - strcat( path, "\\fonts" ); - if( p_dialog ) - dialog_ProgressSet( p_dialog, NULL, 0.4 ); + "This should take less than a few minutes."), NULL ); - FcConfigAppFontAddDir( NULL , path ); - free(path); +/* if( p_dialog ) + dialog_ProgressSet( p_dialog, NULL, 0.5 ); */ + FcConfigBuildFonts( fcConfig ); + t2 = mdate(); + msg_Dbg( p_filter, "Took %ld microseconds", (long)((t2 - t1)) ); if( p_dialog ) - dialog_ProgressSet( p_dialog, NULL, 0.5 ); + { +// dialog_ProgressSet( p_dialog, NULL, 1.0 ); + dialog_ProgressDestroy( p_dialog ); + p_dialog = NULL; + } #endif - mtime_t t1, t2; - - msg_Dbg( p_filter, "Building font database."); - t1 = mdate(); - FcConfigBuildFonts( NULL ); - t2 = mdate(); - - msg_Dbg( p_filter, "Finished building font database." ); - msg_Dbg( p_filter, "Took %ld microseconds", (long)((t2 - t1)) ); + /* Lets find some fontfile from freetype-font variable family */ + char *psz_fontsize; + if( asprintf( &psz_fontsize, "%d", p_sys->i_default_font_size ) == -1 ) + goto error; fontpattern = FcPatternCreate(); - if( !fontpattern ) { msg_Err( p_filter, "Creating fontpattern failed"); goto error; } -#ifdef WIN32 - if( p_dialog ) - dialog_ProgressSet( p_dialog, NULL, 0.7 ); -#endif FcPatternAddString( fontpattern, FC_FAMILY, psz_fontfamily); FcPatternAddString( fontpattern, FC_SIZE, psz_fontsize ); free( psz_fontsize ); @@ -406,10 +395,6 @@ static int Create( vlc_object_t *p_this ) } FcDefaultSubstitute( fontpattern ); -#ifdef WIN32 - if( p_dialog ) - dialog_ProgressSet( p_dialog, NULL, 0.8 ); -#endif /* testing fontresult here doesn't do any good really, but maybe it will * in future as fontconfig code doesn't set it in all cases and just * returns NULL or doesn't set to to Match on all Match cases.*/ @@ -431,20 +416,10 @@ static int Create( vlc_object_t *p_this ) msg_Dbg( p_filter, "Using %s as font from file %s", psz_fontfamily, psz_fontfile ? psz_fontfile : "(null)" ); p_sys->psz_fontfamily = strdup( psz_fontfamily ); -# ifdef WIN32 - if( p_dialog ) - { - dialog_ProgressSet( p_dialog, NULL, 1.0 ); - dialog_ProgressDestroy( p_dialog ); - } -# endif #else -#ifdef HAVE_FONTCONFIG - p_sys->psz_fontfamily = strdup( DEFAULT_FONT ); psz_fontfile = psz_fontfamily; -#endif #endif @@ -504,7 +479,13 @@ error: #ifdef HAVE_FONTCONFIG if( fontmatch ) FcPatternDestroy( fontmatch ); if( fontpattern ) FcPatternDestroy( fontpattern ); + +#ifdef WIN32 + if( p_dialog ) + dialog_ProgressDestroy( p_dialog ); #endif +#endif + if( p_sys->p_face ) FT_Done_Face( p_sys->p_face ); if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library ); free( psz_fontfamily ); @@ -533,7 +514,7 @@ static void Destroy( vlc_object_t *p_this ) } #ifdef HAVE_FONTCONFIG - if( p_sys->p_xml ) xml_Delete( p_sys->p_xml ); + if( p_sys->p_xml ) xml_ReaderDelete( p_sys->p_xml ); free( p_sys->psz_fontfamily ); #endif @@ -553,44 +534,26 @@ static void Destroy( vlc_object_t *p_this ) static int LoadFontsFromAttachments( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; - input_thread_t *p_input; input_attachment_t **pp_attachments; int i_attachments_cnt; - int k; - int rv = VLC_SUCCESS; - p_input = (input_thread_t *)vlc_object_find( p_filter, VLC_OBJECT_INPUT, FIND_PARENT ); - if( ! p_input ) + if( filter_GetInputAttachments( p_filter, &pp_attachments, &i_attachments_cnt ) ) return VLC_EGENERIC; - if( VLC_SUCCESS != input_Control( p_input, INPUT_GET_ATTACHMENTS, &pp_attachments, &i_attachments_cnt )) - { - vlc_object_release(p_input); - return VLC_EGENERIC; - } - p_sys->i_font_attachments = 0; p_sys->pp_font_attachments = malloc( i_attachments_cnt * sizeof( input_attachment_t * )); - if(! p_sys->pp_font_attachments ) - rv = VLC_ENOMEM; + if( !p_sys->pp_font_attachments ) + return VLC_ENOMEM; - for( k = 0; k < i_attachments_cnt; k++ ) + for( int k = 0; k < i_attachments_cnt; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; - if( p_sys->pp_font_attachments ) + if( ( !strcmp( p_attach->psz_mime, "application/x-truetype-font" ) || // TTF + !strcmp( p_attach->psz_mime, "application/x-font-otf" ) ) && // OTF + p_attach->i_data > 0 && p_attach->p_data ) { - if(( !strcmp( p_attach->psz_mime, "application/x-truetype-font" ) || // TTF - !strcmp( p_attach->psz_mime, "application/x-font-otf" ) ) && // OTF - ( p_attach->i_data > 0 ) && - ( p_attach->p_data != NULL ) ) - { - p_sys->pp_font_attachments[ p_sys->i_font_attachments++ ] = p_attach; - } - else - { - vlc_input_attachment_Delete( p_attach ); - } + p_sys->pp_font_attachments[ p_sys->i_font_attachments++ ] = p_attach; } else { @@ -599,9 +562,7 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) } free( pp_attachments ); - vlc_object_release(p_input); - - return rv; + return VLC_SUCCESS; } /***************************************************************************** @@ -638,6 +599,7 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, p_region->p_picture = picture_NewFromFormat( &fmt ); if( !p_region->p_picture ) return VLC_EGENERIC; + fmt.p_palette = p_region->fmt.p_palette ? p_region->fmt.p_palette : malloc(sizeof(*fmt.p_palette)); p_region->fmt = fmt; /* Calculate text color components */ @@ -1259,12 +1221,16 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, } 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 ); + i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_NO_BITMAP | 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_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 ) @@ -1348,7 +1314,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, 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" ) ) + if( var_InheritBool( 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 ); @@ -1490,7 +1456,8 @@ static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, } static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, - bool b_uline, bool b_through, int i_karaoke_bgcolor, + bool b_uline, bool b_through, bool b_bold, + bool b_italic, int i_karaoke_bgcolor, line_desc_t *p_line, uint32_t *psz_unicode, int *pi_pen_x, int i_pen_y, int *pi_start, FT_Vector *p_result ) @@ -1544,14 +1511,28 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, p_line->p_glyph_pos[ i ].x = *pi_pen_x; p_line->p_glyph_pos[ i ].y = i_pen_y; - i_error = FT_Load_Glyph( p_face, i_glyph_index, FT_LOAD_DEFAULT ); + i_error = FT_Load_Glyph( p_face, i_glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_DEFAULT ); if( i_error ) { - msg_Err( p_filter, - "unable to render text FT_Load_Glyph returned %d", i_error ); - p_line->pp_glyphs[ i ] = NULL; - return VLC_EGENERIC; + i_error = FT_Load_Glyph( p_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 ); + p_line->pp_glyphs[ i ] = NULL; + return VLC_EGENERIC; + } } + + /* Do synthetic styling now that Freetype supports it; + * ie. if the font we have loaded is NOT already in the + * style that the tags want, then switch it on; if they + * are then don't. */ + if (b_bold && !( p_face->style_flags & FT_STYLE_FLAG_BOLD )) + FT_GlyphSlot_Embolden( p_face->glyph ); + if (b_italic && !( p_face->style_flags & FT_STYLE_FLAG_ITALIC )) + FT_GlyphSlot_Oblique( p_face->glyph ); + i_error = FT_Get_Glyph( p_face->glyph, &tmp_glyph ); if( i_error ) { @@ -2111,6 +2092,8 @@ static int ProcessLines( filter_t *p_filter, if( RenderTag( p_filter, p_face ? p_face : p_sys->p_face, p_style->i_font_color, p_style->b_underline, p_style->b_through, + p_style->b_bold, + p_style->b_italic, p_style->i_karaoke_bg_color, p_line, psz_unicode, &i_pen_x, i_pen_y, &i_posn, &tmp_result ) != VLC_SUCCESS ) @@ -2207,7 +2190,6 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, { int rv = VLC_SUCCESS; stream_t *p_sub = NULL; - xml_reader_t *p_xml_reader = NULL; if( !p_region_in || !p_region_in->psz_html ) return VLC_EGENERIC; @@ -2219,114 +2201,106 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, (uint8_t *) p_region_in->psz_html, strlen( p_region_in->psz_html ), true ); - if( p_sub ) + if( unlikely(p_sub == NULL) ) + return VLC_SUCCESS; + + xml_reader_t *p_xml_reader = p_filter->p_sys->p_xml; + bool b_karaoke = false; + + if( !p_xml_reader ) + p_xml_reader = xml_ReaderCreate( p_filter, p_sub ); + else + p_xml_reader = xml_ReaderReset( p_xml_reader, p_sub ); + + p_filter->p_sys->p_xml = p_xml_reader; + if( p_xml_reader ) { - if( !p_filter->p_sys->p_xml ) p_filter->p_sys->p_xml = xml_Create( p_filter ); - if( p_filter->p_sys->p_xml ) + /* Look for Root Node */ + if( xml_ReaderRead( p_xml_reader ) == 1 ) { - bool b_karaoke = false; + char *psz_node = xml_ReaderName( p_xml_reader ); - p_xml_reader = xml_ReaderCreate( p_filter->p_sys->p_xml, p_sub ); - if( p_xml_reader ) + if( !strcasecmp( "karaoke", psz_node ) ) { - /* Look for Root Node */ - if( xml_ReaderRead( p_xml_reader ) == 1 ) - { - char *psz_node = xml_ReaderName( p_xml_reader ); - - if( !strcasecmp( "karaoke", psz_node ) ) - { - /* We're going to have to render the text a number - * of times to show the progress marker on the text. - */ - var_SetBool( p_filter, "text-rerender", true ); - b_karaoke = true; - } - else if( !strcasecmp( "text", psz_node ) ) - { - b_karaoke = false; - } - else - { - /* Only text and karaoke tags are supported */ - msg_Dbg( p_filter, "Unsupported top-level tag '%s' ignored.", psz_node ); - xml_ReaderDelete( p_filter->p_sys->p_xml, p_xml_reader ); - p_xml_reader = NULL; - rv = VLC_EGENERIC; - } - - free( psz_node ); - } + /* We're going to have to render the text a number + * of times to show the progress marker on the text. + */ + var_SetBool( p_filter, "text-rerender", true ); + b_karaoke = true; } - - if( p_xml_reader ) + else if( !strcasecmp( "text", psz_node ) ) { - uint32_t *psz_text; - int i_len = 0; - uint32_t i_runs = 0; - uint32_t i_k_runs = 0; - uint32_t *pi_run_lengths = NULL; - uint32_t *pi_k_run_lengths = NULL; - uint32_t *pi_k_durations = NULL; - ft_style_t **pp_styles = NULL; - FT_Vector result; - line_desc_t *p_lines = NULL; - - psz_text = (uint32_t *)malloc( strlen( p_region_in->psz_html ) * - sizeof( uint32_t ) ); - if( psz_text ) - { - uint32_t k; - - rv = ProcessNodes( p_filter, p_xml_reader, - p_region_in->p_style, psz_text, &i_len, - &i_runs, &pi_run_lengths, &pp_styles, + b_karaoke = false; + } + else + { + /* Only text and karaoke tags are supported */ + msg_Dbg( p_filter, "Unsupported top-level tag '%s' ignored.", psz_node ); + p_filter->p_sys->p_xml = xml_ReaderReset( p_xml_reader, NULL ); + p_xml_reader = NULL; + rv = VLC_EGENERIC; + } - b_karaoke, &i_k_runs, &pi_k_run_lengths, - &pi_k_durations ); + free( psz_node ); + } + } - p_region_out->i_x = p_region_in->i_x; - p_region_out->i_y = p_region_in->i_y; + if( p_xml_reader ) + { + uint32_t *psz_text; + int i_len = 0; + uint32_t i_runs = 0; + uint32_t i_k_runs = 0; + uint32_t *pi_run_lengths = NULL; + uint32_t *pi_k_run_lengths = NULL; + uint32_t *pi_k_durations = NULL; + ft_style_t **pp_styles = NULL; + FT_Vector result; + line_desc_t *p_lines = NULL; + + psz_text = (uint32_t *)malloc( strlen( p_region_in->psz_html ) * + sizeof( uint32_t ) ); + if( psz_text ) + { + rv = ProcessNodes( p_filter, p_xml_reader, + p_region_in->p_style, psz_text, &i_len, + &i_runs, &pi_run_lengths, &pp_styles, + b_karaoke, &i_k_runs, &pi_k_run_lengths, + &pi_k_durations ); - if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) - { - rv = ProcessLines( p_filter, psz_text, i_len, i_runs, - pi_run_lengths, pp_styles, &p_lines, &result, - b_karaoke, i_k_runs, pi_k_run_lengths, - pi_k_durations ); - } + p_region_out->i_x = p_region_in->i_x; + p_region_out->i_y = p_region_in->i_y; - for( k=0; k 0 )) + { + rv = ProcessLines( p_filter, psz_text, i_len, i_runs, + pi_run_lengths, pp_styles, &p_lines, + &result, b_karaoke, i_k_runs, + pi_k_run_lengths, pi_k_durations ); + } - /* Don't attempt to render text that couldn't be layed out - * properly. - */ - if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) - { - 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 ); - } - } - } - FreeLines( p_lines ); + for( uint_fast32_t k=0; kp_sys->p_xml, p_xml_reader ); + /* Don't attempt to render text that couldn't be layed out + * properly. */ + if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) + { + if( var_InheritBool( 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 ); } } - stream_Delete( p_sub ); + p_filter->p_sys->p_xml = xml_ReaderReset( p_xml_reader, NULL ); + FreeLines( p_lines ); } - + stream_Delete( p_sub ); return rv; }