X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Ffreetype.c;h=7ea939e1312294194e9de020077f4132ab17cb36;hb=a7c0e2a065b845e9bdd7f00bb7bd8e86a93b5dbe;hp=e6090cac54785116528dccfe418a4f53b720177a;hpb=15643af12d9eb61eff8a8e89d8170f3d2b73d7e1;p=vlc diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index e6090cac54..7ea939e131 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -31,11 +31,8 @@ # include "config.h" #endif -#include - #include #include -#include #include #include #include @@ -45,9 +42,9 @@ #include #include -#include #include +#include #include FT_FREETYPE_H #include FT_GLYPH_H #define FT_FLOOR(X) ((X & -64) >> 6) @@ -96,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") @@ -116,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[] = { @@ -220,7 +217,7 @@ struct line_desc_t uint8_t *p_fg_bg_ratio; /* 0x00=100% FG --> 0x7F=100% BG */ bool b_new_color_mode; /** underline information -- only supplied if text should be underlined */ - uint16_t *pi_underline_offset; + int *pi_underline_offset; uint16_t *pi_underline_thickness; int i_height; @@ -240,6 +237,7 @@ typedef struct bool b_italic; bool b_bold; bool b_underline; + bool b_through; char *psz_fontname; } ft_style_t; @@ -347,57 +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; - path = (char *)malloc( 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 - */ - assert( path ); - GetWindowsDirectory( path, PATH_MAX + 1 ); - strcat( path, "\\fonts" ); - if( p_dialog ) - dialog_ProgressSet( p_dialog, NULL, 0.4 ); - - FcConfigAppFontAddDir( NULL , path ); - free(path); - + "This should take less than a few minutes."), NULL ); if( p_dialog ) dialog_ProgressSet( p_dialog, NULL, 0.5 ); -#endif - mtime_t t1, t2; - msg_Dbg( p_filter, "Building font database."); - t1 = mdate(); - FcConfigBuildFonts( NULL ); + FcConfigBuildFonts( fcConfig ); t2 = mdate(); - - msg_Dbg( p_filter, "Finished building font database." ); msg_Dbg( p_filter, "Took %ld microseconds", (long)((t2 - t1)) ); - fontpattern = FcPatternCreate(); + if( p_dialog ) + { + dialog_ProgressSet( p_dialog, NULL, 1.0 ); + dialog_ProgressDestroy( p_dialog ); + p_dialog = NULL; + } +#endif + /* 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 ); @@ -409,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,22 +413,13 @@ static int Create( vlc_object_t *p_this ) goto error; } - msg_Dbg( p_filter, "Using %s as font from file %s", psz_fontfamily, psz_fontfile ); + 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 @@ -462,12 +435,14 @@ static int Create( vlc_object_t *p_this ) if( i_error == FT_Err_Unknown_File_Format ) { - msg_Err( p_filter, "file %s have unknown format", psz_fontfile ); + msg_Err( p_filter, "file %s have unknown format", + psz_fontfile ? psz_fontfile : "(null)" ); goto error; } else if( i_error ) { - msg_Err( p_filter, "failed to load font file %s", psz_fontfile ); + msg_Err( p_filter, "failed to load font file %s", + psz_fontfile ? psz_fontfile : "(null)" ); goto error; } @@ -505,6 +480,12 @@ error: if( fontmatch ) FcPatternDestroy( fontmatch ); if( fontpattern ) FcPatternDestroy( fontpattern ); #endif + +#ifdef WIN32 + if( p_dialog ) + dialog_ProgressDestroy( p_dialog ); +#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 ); @@ -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; } /***************************************************************************** @@ -626,7 +587,6 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, /* Create a new subpicture region */ memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = VLC_CODEC_YUVP; - fmt.i_aspect = 0; fmt.i_width = fmt.i_visible_width = i_width + 4; fmt.i_height = fmt.i_visible_height = i_height + 4; if( p_region->fmt.i_visible_width > 0 ) @@ -636,9 +596,10 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region, fmt.i_x_offset = fmt.i_y_offset = 0; assert( !p_region->p_picture ); - p_region->p_picture = picture_New( fmt.i_chroma, fmt.i_width, fmt.i_height, fmt.i_aspect ); + 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 */ @@ -781,8 +742,9 @@ static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, bool b_ bool b_ok = true; /* break the underline around the tails of any glyphs which cross it */ + /* Strikethrough doesn't get broken */ for( z = x - i_line_thickness; - z < x + i_line_thickness && b_ok; + z < x + i_line_thickness && b_ok && (i_line_offset >= 0); z++ ) { if( p_next_glyph && ( z >= i_extra ) ) @@ -892,7 +854,6 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, /* Create a new subpicture region */ memset( &fmt, 0, sizeof(video_format_t) ); fmt.i_chroma = VLC_CODEC_YUVA; - fmt.i_aspect = 0; fmt.i_width = fmt.i_visible_width = i_width + 6; fmt.i_height = fmt.i_visible_height = i_height + 6; if( p_region->fmt.i_visible_width > 0 ) @@ -901,7 +862,7 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, fmt.i_visible_height = p_region->fmt.i_visible_height; fmt.i_x_offset = fmt.i_y_offset = 0; - p_region->p_picture = picture_New( fmt.i_chroma, fmt.i_width, fmt.i_height, fmt.i_aspect ); + p_region->p_picture = picture_NewFromFormat( &fmt ); if( !p_region->p_picture ) return VLC_EGENERIC; p_region->fmt = fmt; @@ -1168,7 +1129,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, /* Do bidi conversion line-by-line */ while( pos < i_string_length ) { - while( pos < i_string_length ) + while( pos < i_string_length ) { i_char = psz_unicode[pos]; if (i_char != '\r' && i_char != '\n') @@ -1260,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 ) @@ -1349,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 ); @@ -1367,7 +1332,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, #ifdef HAVE_FONTCONFIG static 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 ) + bool b_italic, bool b_uline, bool b_through ) { ft_style_t *p_style = malloc( sizeof( ft_style_t )); @@ -1379,6 +1344,7 @@ static ft_style_t *CreateStyle( char *psz_fontname, int i_font_size, p_style->b_italic = b_italic; p_style->b_bold = b_bold; p_style->b_underline = b_uline; + p_style->b_through = b_through; p_style->psz_fontname = strdup( psz_fontname ); } @@ -1404,6 +1370,7 @@ static bool StyleEquals( ft_style_t *s1, ft_style_t *s2 ) 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_through == s2->b_through ) && ( s1->b_bold == s2->b_bold ) && ( s1->b_underline == s2->b_underline ) && ( !strcmp( s1->psz_fontname, s2->psz_fontname ))) @@ -1470,7 +1437,7 @@ static void IconvText( filter_t *p_filter, const char *psz_string, static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, font_stack_t **p_fonts, bool b_bold, bool b_italic, - bool b_uline ) + bool b_uline, bool b_through ) { ft_style_t *p_style = NULL; @@ -1483,13 +1450,14 @@ static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, &i_font_color, &i_karaoke_bg_color )) { p_style = CreateStyle( psz_fontname, i_font_size, i_font_color, - i_karaoke_bg_color, b_bold, b_italic, b_uline ); + i_karaoke_bg_color, b_bold, b_italic, b_uline, b_through ); } return p_style; } static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, - bool b_uline, 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 ) @@ -1543,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 ) { @@ -1566,7 +1548,7 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, FT_Done_Glyph( tmp_glyph ); continue; } - if( b_uline ) + if( b_uline || b_through ) { float aOffset = FT_FLOOR(FT_MulFix(p_face->underline_position, p_face->size->metrics.y_scale)); @@ -1577,7 +1559,19 @@ static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, ( aOffset < 0 ) ? -aOffset : aOffset; p_line->pi_underline_thickness[ i ] = ( aSize < 0 ) ? -aSize : aSize; + if (b_through) + { + /* Move the baseline to make it strikethrough instead of + * underline. That means that strikethrough takes precedence + */ + float aDescent = FT_FLOOR(FT_MulFix(p_face->descender*2, + p_face->size->metrics.y_scale)); + + p_line->pi_underline_offset[ i ] -= + ( aDescent < 0 ) ? -aDescent : aDescent; + } } + p_line->pp_glyphs[ i ] = (FT_BitmapGlyph)tmp_glyph; p_line->p_fg_rgb[ i ] = i_font_color & 0x00ffffff; p_line->p_bg_rgb[ i ] = i_karaoke_bgcolor & 0x00ffffff; @@ -2097,6 +2091,9 @@ 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 ) @@ -2293,7 +2290,7 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, */ if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) { - 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 ); @@ -2395,13 +2392,14 @@ static void SetupLine( filter_t *p_filter, const char *psz_text_in, static ft_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, font_stack_t **p_fonts, bool b_bold, bool b_italic, - bool b_uline ) + bool b_uline, bool b_through ) { VLC_UNUSED(p_sys); VLC_UNUSED(p_fonts); VLC_UNUSED(b_bold); VLC_UNUSED(b_italic); VLC_UNUSED(b_uline); + VLC_UNUSED(b_through); return NULL; } #endif @@ -2450,7 +2448,7 @@ static line_desc_t *NewLine( int i_count ) p_line->p_fg_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); p_line->p_bg_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); p_line->p_fg_bg_ratio = calloc( i_count + 1, sizeof( uint8_t ) ); - p_line->pi_underline_offset = calloc( i_count + 1, sizeof( uint16_t ) ); + p_line->pi_underline_offset = calloc( i_count + 1, sizeof( int ) ); p_line->pi_underline_thickness = calloc( i_count + 1, sizeof( uint16_t ) ); if( ( p_line->pp_glyphs == NULL ) || ( p_line->p_glyph_pos == NULL ) ||