X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Ftext_renderer%2Ffreetype.c;h=cdc92430c65fc224b628fdb268a71f9fa0fa2887;hb=dcd2493220dc1f8b2fd91520b27793892d7f44f3;hp=10c81508c4ea2092df760b13df519e720a40d312;hpb=6d0aeeec5e58e73a8bcc851723165e603e5108cb;p=vlc diff --git a/modules/text_renderer/freetype.c b/modules/text_renderer/freetype.c index 10c81508c4..cdc92430c6 100644 --- a/modules/text_renderer/freetype.c +++ b/modules/text_renderer/freetype.c @@ -1,27 +1,28 @@ /***************************************************************************** * freetype.c : Put text on the video, using freetype2 ***************************************************************************** - * Copyright (C) 2002 - 2011 the VideoLAN team + * Copyright (C) 2002 - 2012 VLC authors and VideoLAN * $Id$ * * Authors: Sigmund Augdal Helberg * Gildas Bazin * Bernie Purcell * Jean-Baptiste Kempf + * Felix Paul Kühne * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -46,17 +47,46 @@ /* Default fonts */ #ifdef __APPLE__ -# define DEFAULT_FONT_FILE "/Library/Fonts/Arial Black.ttf" -# define DEFAULT_FAMILY "Arial Black" -#elif defined( WIN32 ) -# define DEFAULT_FONT_FILE "arial.ttf" /* Default path font found at run-time */ -# define DEFAULT_FAMILY "Arial" -#elif defined( HAVE_MAEMO ) -# define DEFAULT_FONT_FILE "/usr/share/fonts/nokia/nosnb.ttf" -# define DEFAULT_FAMILY "Nokia Sans Bold" +# define SYSTEM_DEFAULT_FONT_FILE "/Library/Fonts/Arial Unicode.ttf" +# define SYSTEM_DEFAULT_FAMILY "Arial Unicode MS" +# define SYSTEM_DEFAULT_MONOSPACE_FONT_FILE "/System/Library/Fonts/Monaco.dfont" +# define SYSTEM_DEFAULT_MONOSPACE_FAMILY "Monaco" +#elif defined( _WIN32 ) +# define SYSTEM_DEFAULT_FONT_FILE "arial.ttf" /* Default path font found at run-time */ +# define SYSTEM_DEFAULT_FAMILY "Arial" +# define SYSTEM_DEFAULT_MONOSPACE_FONT_FILE "cour.ttf" +# define SYSTEM_DEFAULT_MONOSPACE_FAMILY "Courier New" +#elif defined( __OS2__ ) +# define SYSTEM_DEFAULT_FONT_FILE "/psfonts/tnrwt_k.ttf" +# define SYSTEM_DEFAULT_FAMILY "Times New Roman WT K" +# define SYSTEM_DEFAULT_MONOSPACE_FONT_FILE "/psfonts/mtsansdk.ttf" +# define SYSTEM_DEFAULT_MONOSPACE_FAMILY "Monotype Sans Duospace WT K" +#elif defined( __ANDROID__ ) +# define SYSTEM_DEFAULT_FONT_FILE "/system/fonts/DroidSans-Bold.ttf" +# define SYSTEM_DEFAULT_FAMILY "Droid Sans Bold" +# define SYSTEM_DEFAULT_MONOSPACE_FONT_FILE "/system/fonts/DroidSansMono.ttf" +# define SYSTEM_DEFAULT_MONOSPACE_FAMILY "Droid Sans Mono" #else -# define DEFAULT_FONT_FILE "/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf" -# define DEFAULT_FAMILY "Serif Bold" +# define SYSTEM_DEFAULT_FONT_FILE "/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf" +# define SYSTEM_DEFAULT_FAMILY "Serif Bold" +# define SYSTEM_DEFAULT_MONOSPACE_FONT_FILE "/usr/share/fonts/truetype/freefont/FreeMono.ttf" +# define SYSTEM_DEFAULT_MONOSPACE_FAMILY "Monospace" +#endif + +#ifndef DEFAULT_FONT_FILE +#define DEFAULT_FONT_FILE SYSTEM_DEFAULT_FONT_FILE +#endif + +#ifndef DEFAULT_FAMILY +#define DEFAULT_FAMILY SYSTEM_DEFAULT_FAMILY +#endif + +#ifndef DEFAULT_MONOSPACE_FONT_FILE +#define DEFAULT_MONOSPACE_FONT_FILE SYSTEM_DEFAULT_MONOSPACE_FONT_FILE +#endif + +#ifndef DEFAULT_MONOSPACE_FAMILY +#define DEFAULT_MONOSPACE_FAMILY SYSTEM_DEFAULT_MONOSPACE_FAMILY #endif /* Freetype */ @@ -71,13 +101,24 @@ #define FT_MulFix(v, s) (((v)*(s))>>16) #endif +/* apple stuff */ +#ifdef __APPLE__ +#include +#if !TARGET_OS_IPHONE +#include +#endif +#include /* for MAXPATHLEN */ +#undef HAVE_FONTCONFIG +#define HAVE_STYLES +#endif + /* RTL */ #if defined(HAVE_FRIBIDI) # include #endif /* Win32 GDI */ -#ifdef WIN32 +#ifdef _WIN32 # include # include # define HAVE_STYLES @@ -92,6 +133,18 @@ #include +#ifdef __OS2__ +typedef uint16_t uni_char_t; +# define FREETYPE_TO_UCS "UCS-2LE" +#else +typedef uint32_t uni_char_t; +# if defined(WORDS_BIGENDIAN) +# define FREETYPE_TO_UCS "UCS-4BE" +# else +# define FREETYPE_TO_UCS "UCS-4LE" +# endif +#endif + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -99,6 +152,7 @@ static int Create ( vlc_object_t * ); static void Destroy( vlc_object_t * ); #define FONT_TEXT N_("Font") +#define MONOSPACE_FONT_TEXT N_("Monospace Font") #define FAMILY_LONGTEXT N_("Font family for the font you want to use") #define FONT_LONGTEXT N_("Font file for the font you want to use") @@ -108,7 +162,7 @@ static void Destroy( vlc_object_t * ); "that will be rendered on the video. " \ "If set to something different than 0 this option will override the " \ "relative font size." ) -#define OPACITY_TEXT N_("Opacity") +#define OPACITY_TEXT N_("Text opacity") #define OPACITY_LONGTEXT N_("The opacity (inverse of transparency) of the " \ "text that will be rendered on the video. 0 = transparent, " \ "255 = totally opaque. " ) @@ -168,12 +222,15 @@ vlc_module_begin () #ifdef HAVE_STYLES add_font( "freetype-font", DEFAULT_FAMILY, FONT_TEXT, FAMILY_LONGTEXT, false ) + add_font( "freetype-monofont", DEFAULT_MONOSPACE_FAMILY, MONOSPACE_FONT_TEXT, FAMILY_LONGTEXT, false ) #else add_loadfile( "freetype-font", DEFAULT_FONT_FILE, FONT_TEXT, FONT_LONGTEXT, false ) + add_loadfile( "freetype-monofont", DEFAULT_MONOSPACE_FONT_FILE, MONOSPACE_FONT_TEXT, FONT_LONGTEXT, false ) #endif add_integer( "freetype-fontsize", 0, FONTSIZE_TEXT, FONTSIZE_LONGTEXT, true ) + change_integer_range( 0, 4096) change_safe() add_integer( "freetype-rel-fontsize", 16, FONTSIZER_TEXT, @@ -187,46 +244,46 @@ vlc_module_begin () change_safe() /* hook to the color values list, with default 0x00ffffff = white */ - add_integer( "freetype-color", 0x00FFFFFF, COLOR_TEXT, + add_rgb( "freetype-color", 0x00FFFFFF, COLOR_TEXT, COLOR_LONGTEXT, false ) change_integer_list( pi_color_values, ppsz_color_descriptions ) change_safe() - add_bool( "freetype-bold", false, BOLD_TEXT, "", false ) + add_bool( "freetype-bold", false, BOLD_TEXT, NULL, false ) change_safe() add_integer_with_range( "freetype-background-opacity", 0, 0, 255, - BG_OPACITY_TEXT, "", false ) + BG_OPACITY_TEXT, NULL, false ) change_safe() - add_integer( "freetype-background-color", 0x00000000, BG_COLOR_TEXT, - "", false ) + add_rgb( "freetype-background-color", 0x00000000, BG_COLOR_TEXT, + NULL, false ) change_integer_list( pi_color_values, ppsz_color_descriptions ) change_safe() add_integer_with_range( "freetype-outline-opacity", 255, 0, 255, - OUTLINE_OPACITY_TEXT, "", false ) + OUTLINE_OPACITY_TEXT, NULL, false ) change_safe() - add_integer( "freetype-outline-color", 0x00000000, OUTLINE_COLOR_TEXT, - "", false ) + add_rgb( "freetype-outline-color", 0x00000000, OUTLINE_COLOR_TEXT, + NULL, false ) change_integer_list( pi_color_values, ppsz_color_descriptions ) change_safe() add_integer_with_range( "freetype-outline-thickness", 4, 0, 50, OUTLINE_THICKNESS_TEXT, - "", false ) + NULL, false ) change_integer_list( pi_outline_thickness, ppsz_outline_thickness ) change_safe() add_integer_with_range( "freetype-shadow-opacity", 128, 0, 255, - SHADOW_OPACITY_TEXT, "", false ) + SHADOW_OPACITY_TEXT, NULL, false ) change_safe() - add_integer( "freetype-shadow-color", 0x00000000, SHADOW_COLOR_TEXT, - "", false ) + add_rgb( "freetype-shadow-color", 0x00000000, SHADOW_COLOR_TEXT, + NULL, false ) change_integer_list( pi_color_values, ppsz_color_descriptions ) change_safe() add_float_with_range( "freetype-shadow-angle", -45, -360, 360, - SHADOW_ANGLE_TEXT, "", false ) + SHADOW_ANGLE_TEXT, NULL, false ) change_safe() add_float_with_range( "freetype-shadow-distance", 0.06, 0.0, 1.0, - SHADOW_DISTANCE_TEXT, "", false ) + SHADOW_DISTANCE_TEXT, NULL, false ) change_safe() add_obsolete_integer( "freetype-effect" ); @@ -259,6 +316,7 @@ struct line_desc_t line_desc_t *p_next; int i_width; + int i_height; int i_base_line; int i_character_count; line_character_t *p_character; @@ -287,14 +345,9 @@ struct filter_sys_t FT_Face p_face; /* handle to face object */ FT_Stroker p_stroker; uint8_t i_font_opacity; - int i_font_color; int i_font_size; bool b_font_bold; - uint8_t i_background_opacity; - int i_background_color; - - double f_outline_thickness; uint8_t i_outline_opacity; int i_outline_color; @@ -306,11 +359,10 @@ struct filter_sys_t int i_default_font_size; int i_display_height; char* psz_fontfamily; -#ifdef HAVE_STYLES + char* psz_monofontfamily; xml_reader_t *p_xml; -#ifdef WIN32 +#ifdef _WIN32 char* psz_win_fonts_path; -#endif #endif input_attachment_t **pp_font_attachments; @@ -388,7 +440,7 @@ static int GetFontSize( filter_t *p_filter ) } else { - int i_ratio = var_GetInteger( p_filter, "freetype-rel-fontsize" ); + int i_ratio = var_InheritInteger( p_filter, "freetype-rel-fontsize" ); if( i_ratio > 0 ) { i_size = (int)p_filter->fmt_out.video.i_height / i_ratio; @@ -434,7 +486,11 @@ static void FontConfig_BuildCache( filter_t *p_filter ) mtime_t t1, t2; t1 = mdate(); -#ifdef WIN32 +#ifdef __OS2__ + FcInit(); +#endif + +#if defined( _WIN32 ) || defined( __APPLE__ ) dialog_progress_bar_t *p_dialog = NULL; FcConfig *fcConfig = FcInitLoadConfig(); @@ -447,6 +503,15 @@ static void FontConfig_BuildCache( filter_t *p_filter ) dialog_ProgressSet( p_dialog, NULL, 0.5 ); */ FcConfigBuildFonts( fcConfig ); +#if defined( __APPLE__ ) + // By default, scan only the directory /System/Library/Fonts. + // So build the set of available fonts under another directories, + // and add the set to the current configuration. + FcConfigAppFontAddDir( NULL, "~/Library/Fonts" ); + FcConfigAppFontAddDir( NULL, "/Library/Fonts" ); + FcConfigAppFontAddDir( NULL, "/Network/Library/Fonts" ); + //FcConfigAppFontAddDir( NULL, "/System/Library/Fonts" ); +#endif if( p_dialog ) { // dialog_ProgressSet( p_dialog, NULL, 1.0 ); @@ -468,6 +533,7 @@ static char* FontConfig_Select( FcConfig* config, const char* family, FcPattern *pat, *p_pat; FcChar8* val_s; FcBool val_b; + char *ret = NULL; /* Create a pattern and fills it */ pat = FcPatternCreate(); @@ -524,56 +590,70 @@ static char* FontConfig_Select( FcConfig* config, const char* family, "the requested one: '%s' != '%s'\n", (const char*)val_s, family ); */ - if( FcResultMatch != FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) ) - { - FcPatternDestroy( p_pat ); - return NULL; - } + if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) ) + ret = strdup( (const char*)val_s ); FcPatternDestroy( p_pat ); - return strdup( (const char*)val_s ); + return ret; } #endif -#ifdef WIN32 -#define UNICODE -#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" +#ifdef _WIN32 +#define FONT_DIR_NT _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts") -static int GetFileFontByName( const char *font_name, char **psz_filename ) +static int GetFileFontByName( LPCTSTR font_name, char **psz_filename ) { HKEY hKey; - wchar_t vbuffer[MAX_PATH]; - wchar_t dbuffer[256]; + TCHAR vbuffer[MAX_PATH]; + TCHAR dbuffer[256]; - if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, FONT_DIR_NT, 0, KEY_READ, &hKey) != ERROR_SUCCESS ) + if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, FONT_DIR_NT, 0, KEY_READ, &hKey) + != ERROR_SUCCESS ) return 1; + char *font_name_temp = FromT( font_name ); + size_t fontname_len = strlen( font_name_temp ); + for( int index = 0;; index++ ) { DWORD vbuflen = MAX_PATH - 1; DWORD dbuflen = 255; - if( RegEnumValueW( hKey, index, vbuffer, &vbuflen, - NULL, NULL, (LPBYTE)dbuffer, &dbuflen) != ERROR_SUCCESS ) - return 2; + LONG i_result = RegEnumValue( hKey, index, vbuffer, &vbuflen, + NULL, NULL, (LPBYTE)dbuffer, &dbuflen); + if( i_result != ERROR_SUCCESS ) + { + RegCloseKey( hKey ); + return i_result; + } - char *psz_value = FromWide( vbuffer ); + char *psz_value = FromT( vbuffer ); char *s = strchr( psz_value,'(' ); if( s != NULL && s != psz_value ) s[-1] = '\0'; /* Manage concatenated font names */ if( strchr( psz_value, '&') ) { - if( strcasestr( psz_value, font_name ) != NULL ) + if( strcasestr( psz_value, font_name_temp ) != NULL ) + { + free( psz_value ); break; + } } else { - if( strcasecmp( psz_value, font_name ) == 0 ) + if( strncasecmp( psz_value, font_name_temp, fontname_len ) == 0 ) + { + free( psz_value ); break; + } } + + free( psz_value ); } - *psz_filename = FromWide( dbuffer ); + *psz_filename = FromT( dbuffer ); + free( font_name_temp ); + RegCloseKey( hKey ); return 0; } @@ -585,14 +665,16 @@ static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *lpelfe, const NEWTEXTM if( (type & RASTER_FONTTYPE) ) return 1; // if( lpelfe->elfScript ) FIXME - return GetFileFontByName( (const char *)lpelfe->elfFullName, (char **)lParam ); + return GetFileFontByName( (LPCTSTR)lpelfe->elfFullName, (char **)lParam ); } static char* Win32_Select( filter_t *p_filter, const char* family, bool b_bold, bool b_italic, int i_size, int *i_idx ) { VLC_UNUSED( i_size ); - // msg_Dbg( p_filter, "Here in Win32_Select, asking for %s", family ); + + if( !family || strlen( family ) < 1 ) + goto fail; /* */ LOGFONT lf; @@ -601,7 +683,10 @@ static char* Win32_Select( filter_t *p_filter, const char* family, lf.lfItalic = true; if( b_bold ) lf.lfWeight = FW_BOLD; - strncpy( (LPSTR)&lf.lfFaceName, family, 32); + + LPTSTR psz_fbuffer = ToT( family ); + _tcsncpy( (LPTSTR)&lf.lfFaceName, psz_fbuffer, LF_FACESIZE ); + free( psz_fbuffer ); /* */ char *psz_filename = NULL; @@ -609,22 +694,124 @@ static char* Win32_Select( filter_t *p_filter, const char* family, EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&psz_filename, 0); ReleaseDC(NULL, hDC); - if( psz_filename == NULL ) + /* */ + if( psz_filename != NULL ) + { + /* FIXME: increase i_idx, when concatenated strings */ + i_idx = 0; + + /* Prepend the Windows Font path, when only a filename was provided */ + if( strchr( psz_filename, DIR_SEP_CHAR ) ) + return psz_filename; + else + { + char *psz_tmp; + if( asprintf( &psz_tmp, "%s\\%s", p_filter->p_sys->psz_win_fonts_path, psz_filename ) == -1 ) + { + free( psz_filename ); + return NULL; + } + free( psz_filename ); + return psz_tmp; + } + } + else /* Let's take any font we can */ +fail: + { + char *psz_tmp; + if( asprintf( &psz_tmp, "%s\\%s", p_filter->p_sys->psz_win_fonts_path, "arial.ttf" ) == -1 ) + return NULL; + else + return psz_tmp; + } +} +#endif /* _WIN32 */ + +#ifdef __APPLE__ +#if !TARGET_OS_IPHONE +static char* MacLegacy_Select( filter_t *p_filter, const char* psz_fontname, + bool b_bold, bool b_italic, int i_size, int *i_idx ) +{ + VLC_UNUSED( b_bold ); + VLC_UNUSED( b_italic ); + VLC_UNUSED( i_size ); + FSRef ref; + unsigned char path[MAXPATHLEN]; + char * psz_path; + + CFStringRef cf_fontName; + ATSFontRef ats_font_id; + + *i_idx = 0; + + if( psz_fontname == NULL ) return NULL; - /* FIXME: increase i_idx, when concatenated strings */ - i_idx = 0; + msg_Dbg( p_filter, "looking for %s", psz_fontname ); + cf_fontName = CFStringCreateWithCString( kCFAllocatorDefault, psz_fontname, kCFStringEncodingUTF8 ); - /* */ - char *psz_tmp; - if( asprintf( &psz_tmp, "%s\\%s", p_filter->p_sys->psz_win_fonts_path, psz_filename ) == -1 ) + ats_font_id = ATSFontFindFromName( cf_fontName, kATSOptionFlagsIncludeDisabledMask ); + + if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) + { + msg_Dbg( p_filter, "ATS couldn't find %s by name, checking family", psz_fontname ); + ats_font_id = ATSFontFamilyFindFromName( cf_fontName, kATSOptionFlagsDefault ); + + if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) + { + msg_Dbg( p_filter, "ATS couldn't find either %s nor its family, checking PS name", psz_fontname ); + ats_font_id = ATSFontFindFromPostScriptName( cf_fontName, kATSOptionFlagsDefault ); + + if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) + { + msg_Err( p_filter, "ATS couldn't find %s (no font name, family or PS name)", psz_fontname ); + CFRelease( cf_fontName ); + return NULL; + } + } + } + CFRelease( cf_fontName ); + + if ( noErr != ATSFontGetFileReference( ats_font_id, &ref ) ) + { + msg_Err( p_filter, "ATS couldn't get file ref for %s", psz_fontname ); return NULL; - return psz_tmp; + } + + /* i_idx calculation by searching preceding fontIDs */ + /* with same FSRef */ + { + ATSFontRef id2 = ats_font_id - 1; + FSRef ref2; + + while ( id2 > 0 ) + { + if ( noErr != ATSFontGetFileReference( id2, &ref2 ) ) + break; + if ( noErr != FSCompareFSRefs( &ref, &ref2 ) ) + break; + + id2 --; + } + *i_idx = ats_font_id - ( id2 + 1 ); + } + + if ( noErr != FSRefMakePath( &ref, path, sizeof(path) ) ) + { + msg_Err( p_filter, "failure when getting path from FSRef" ); + return NULL; + } + msg_Dbg( p_filter, "found %s", path ); + + psz_path = strdup( (char *)path ); + + return psz_path; } #endif - #endif +#endif /* HAVE_STYLES */ + /***************************************************************************** * RenderYUVP: place string in picture @@ -882,6 +1069,93 @@ static inline void BlendAXYZLine( picture_t *p_picture, } } +static inline void RenderBackground( subpicture_region_t *p_region, + line_desc_t *p_line_head, + FT_BBox *p_bbox, + int i_margin, + picture_t *p_picture, + int i_text_width, + void (*ExtractComponents)( uint32_t, uint8_t *, uint8_t *, uint8_t * ), + void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) ) +{ + for( line_desc_t *p_line = p_line_head; p_line != NULL; p_line = p_line->p_next ) + { + int i_align_left = i_margin; + int i_align_top = i_margin; + int line_start = 0; + int line_end = 0; + unsigned line_top = 0; + int line_bottom = 0; + int max_height = 0; + + if( p_line->i_width < i_text_width ) + { + /* Left offset to take into account alignment */ + if( (p_region->i_align & 0x3) == SUBPICTURE_ALIGN_RIGHT ) + i_align_left += ( i_text_width - p_line->i_width ); + else if( (p_region->i_align & 0x10) == SUBPICTURE_ALIGN_LEAVETEXT) + i_align_left = i_margin; /* Keep it the way it is */ + else if( (p_region->i_align & 0x3) != SUBPICTURE_ALIGN_LEFT ) + i_align_left += ( i_text_width - p_line->i_width ) / 2; + } + + /* Find the tallest character in the line */ + for( int i = 0; i < p_line->i_character_count; i++ ) { + const line_character_t *ch = &p_line->p_character[i]; + FT_BitmapGlyph p_glyph = ch->p_outline ? ch->p_outline : ch->p_glyph; + if (p_glyph->top > max_height) + max_height = p_glyph->top; + } + + /* Compute the background for the line (identify leading/trailing space) */ + for( int i = 0; i < p_line->i_character_count; i++ ) { + const line_character_t *ch = &p_line->p_character[i]; + FT_BitmapGlyph p_glyph = ch->p_outline ? ch->p_outline : ch->p_glyph; + if (p_glyph && p_glyph->bitmap.rows > 0) { + // Found a non-whitespace character + line_start = i_align_left + p_glyph->left - p_bbox->xMin; + break; + } + } + + /* Fudge factor to make sure caption background edges are left aligned + despite variable font width */ + if (line_start < 12) + line_start = 0; + + /* Find right boundary for bounding box for background */ + for( int i = p_line->i_character_count; i > 0; i-- ) { + const line_character_t *ch = &p_line->p_character[i - 1]; + FT_BitmapGlyph p_glyph = ch->p_shadow ? ch->p_shadow : ch->p_glyph; + if (p_glyph && p_glyph->bitmap.rows > 0) { + // Found a non-whitespace character + line_end = i_align_left + p_glyph->left - p_bbox->xMin + p_glyph->bitmap.width; + break; + } + } + + /* Setup color for the background */ + uint8_t i_x, i_y, i_z; + ExtractComponents( 0x000000, &i_x, &i_y, &i_z ); + + /* Compute the upper boundary for the background */ + if ((i_align_top + p_line->i_base_line - max_height) < 0) + line_top = i_align_top + p_line->i_base_line; + else + line_top = i_align_top + p_line->i_base_line - max_height; + + /* Compute lower boundary for the background */ + line_bottom = __MIN(line_top + p_line->i_height, p_region->fmt.i_visible_height); + + /* Render the actual background */ + for( int dy = line_top; dy < line_bottom; dy++ ) + { + for( int dx = line_start; dx < line_end; dx++ ) + BlendPixel( p_picture, dx, dy, 0xff, i_x, i_y, i_z, 0xff ); + } + } +} + static inline int RenderAXYZ( filter_t *p_filter, subpicture_region_t *p_region, line_desc_t *p_line_head, @@ -910,11 +1184,22 @@ static inline int RenderAXYZ( filter_t *p_filter, p_region->fmt = fmt; /* Initialize the picture background */ - uint8_t i_a = p_sys->i_background_opacity; + uint8_t i_a = var_InheritInteger( p_filter, "freetype-background-opacity" ); + i_a = VLC_CLIP( i_a, 0, 255 ); uint8_t i_x, i_y, i_z; - ExtractComponents( p_sys->i_background_color, &i_x, &i_y, &i_z ); - FillPicture( p_picture, i_a, i_x, i_y, i_z ); + if (p_region->b_renderbg) { + /* Render the background just under the text */ + FillPicture( p_picture, 0x00, 0x00, 0x00, 0x00 ); + RenderBackground(p_region, p_line_head, p_bbox, i_margin, p_picture, i_text_width, + ExtractComponents, BlendPixel); + } else { + /* Render background under entire subpicture block */ + int i_background_color = var_InheritInteger( p_filter, "freetype-background-color" ); + i_background_color = VLC_CLIP( i_background_color, 0, 0xFFFFFF ); + ExtractComponents( i_background_color, &i_x, &i_y, &i_z ); + FillPicture( p_picture, i_a, i_x, i_y, i_z ); + } /* Render shadow then outline and then normal glyphs */ for( int g = 0; g < 3; g++ ) @@ -928,6 +1213,8 @@ static inline int RenderAXYZ( filter_t *p_filter, /* Left offset to take into account alignment */ if( (p_region->i_align & 0x3) == SUBPICTURE_ALIGN_RIGHT ) i_align_left += ( i_text_width - p_line->i_width ); + else if( (p_region->i_align & 0x10) == SUBPICTURE_ALIGN_LEAVETEXT) + i_align_left = i_margin; /* Keep it the way it is */ else if( (p_region->i_align & 0x3) != SUBPICTURE_ALIGN_LEFT ) i_align_left += ( i_text_width - p_line->i_width ) / 2; } @@ -1280,7 +1567,6 @@ static int HandleFontAttributes( xml_reader_t *p_xml_reader, &i_karaoke_bg_color )) { psz_fontname = strdup( psz_fontname ); - i_font_size = i_font_size; } i_font_alpha = (i_font_color >> 24) & 0xff; i_font_color &= 0x00ffffff; @@ -1350,6 +1636,30 @@ static int HandleFontAttributes( xml_reader_t *p_xml_reader, return rv; } +static int HandleTT(font_stack_t **p_fonts, const char *p_fontfamily ) +{ + char *psz_unused_fontname = NULL; + uint32_t i_font_color = 0xffffff; + uint32_t i_karaoke_bg_color = 0x00ffffff; + int i_font_size = 24; + + /* Default all attributes to the top font in the stack -- in case not + * all attributes are specified in the sub-font + */ + PeekFont( p_fonts, + &psz_unused_fontname, + &i_font_size, + &i_font_color, + &i_karaoke_bg_color ); + + /* Keep all the parent's font attributes, but change to a monospace font */ + return PushFont( p_fonts, + p_fontfamily, + i_font_size, + i_font_color, + i_karaoke_bg_color ); +} + /* Turn any multiple-whitespaces into single spaces */ static void HandleWhiteSpace( char *psz_node ) { @@ -1369,14 +1679,16 @@ static void HandleWhiteSpace( char *psz_node ) } -static text_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, +static text_style_t *GetStyleFromFontStack( filter_t *p_filter, font_stack_t **p_fonts, int i_style_flags ) { char *psz_fontname = NULL; - uint32_t i_font_color = p_sys->i_font_color & 0x00ffffff; + uint32_t i_font_color = var_InheritInteger( p_filter, "freetype-color" ); + i_font_color = VLC_CLIP( i_font_color, 0, 0xFFFFFF ); + i_font_color = i_font_color & 0x00ffffff; + int i_font_size = p_filter->p_sys->i_font_size; uint32_t i_karaoke_bg_color = i_font_color; - int i_font_size = p_sys->i_font_size; if( PeekFont( p_fonts, &psz_fontname, &i_font_size, &i_font_color, &i_karaoke_bg_color ) ) @@ -1388,7 +1700,7 @@ static text_style_t *GetStyleFromFontStack( filter_sys_t *p_sys, } static unsigned SetupText( filter_t *p_filter, - uint32_t *psz_text_out, + uni_char_t *psz_text_out, text_style_t **pp_styles, uint32_t *pi_k_dates, @@ -1399,15 +1711,11 @@ static unsigned SetupText( filter_t *p_filter, size_t i_string_length; size_t i_string_bytes; -#if defined(WORDS_BIGENDIAN) - uint32_t *psz_tmp = ToCharset( "UCS-4BE", psz_text_in, &i_string_bytes ); -#else - uint32_t *psz_tmp = ToCharset( "UCS-4LE", psz_text_in, &i_string_bytes ); -#endif + uni_char_t *psz_tmp = ToCharset( FREETYPE_TO_UCS, psz_text_in, &i_string_bytes ); if( psz_tmp ) { memcpy( psz_text_out, psz_tmp, i_string_bytes ); - i_string_length = i_string_bytes / 4; + i_string_length = i_string_bytes / sizeof( *psz_tmp ); free( psz_tmp ); } else @@ -1434,7 +1742,7 @@ static unsigned SetupText( filter_t *p_filter, } static int ProcessNodes( filter_t *p_filter, - uint32_t *psz_text, + uni_char_t *psz_text, text_style_t **pp_styles, uint32_t *pi_k_dates, int *pi_len, @@ -1451,9 +1759,14 @@ static int ProcessNodes( filter_t *p_filter, if( p_font_style ) { + /* If the font is not specified in the style, assume the system font */ + if(!p_font_style->psz_fontname) + p_font_style->psz_fontname = strdup(p_sys->psz_fontfamily); + rv = PushFont( &p_fonts, p_font_style->psz_fontname, - p_font_style->i_font_size, + p_font_style->i_font_size > 0 ? p_font_style->i_font_size + : p_sys->i_font_size, (p_font_style->i_font_color & 0xffffff) | ((p_font_style->i_font_alpha & 0xff) << 24), (p_font_style->i_karaoke_background_color & 0xffffff) | @@ -1464,17 +1777,19 @@ static int ProcessNodes( filter_t *p_filter, STYLE_UNDERLINE | STYLE_STRIKEOUT); } -#ifdef HAVE_STYLES else { + uint32_t i_font_size = p_sys->i_font_size; + uint32_t i_font_color = var_InheritInteger( p_filter, "freetype-color" ); + i_font_color = VLC_CLIP( i_font_color, 0, 0xFFFFFF ); + uint32_t i_font_opacity = p_sys->i_font_opacity; rv = PushFont( &p_fonts, p_sys->psz_fontfamily, - p_sys->i_font_size, - (p_sys->i_font_color & 0xffffff) | - ((p_sys->i_font_opacity & 0xff) << 24), + i_font_size, + (i_font_color & 0xffffff) | + ((i_font_opacity & 0xff) << 24), 0x00ffffff ); } -#endif if( p_sys->b_font_bold ) i_style_flags |= STYLE_BOLD; @@ -1491,6 +1806,8 @@ static int ProcessNodes( filter_t *p_filter, case XML_READER_ENDELEM: if( !strcasecmp( "font", node ) ) PopFont( &p_fonts ); + else if( !strcasecmp( "tt", node ) ) + PopFont( &p_fonts ); else if( !strcasecmp( "b", node ) ) i_style_flags &= ~STYLE_BOLD; else if( !strcasecmp( "i", node ) ) @@ -1504,6 +1821,8 @@ static int ProcessNodes( filter_t *p_filter, case XML_READER_STARTELEM: if( !strcasecmp( "font", node ) ) HandleFontAttributes( p_xml_reader, &p_fonts ); + else if( !strcasecmp( "tt", node ) ) + HandleTT( &p_fonts, p_sys->psz_monofontfamily ); else if( !strcasecmp( "b", node ) ) i_style_flags |= STYLE_BOLD; else if( !strcasecmp( "i", node ) ) @@ -1519,7 +1838,7 @@ static int ProcessNodes( filter_t *p_filter, &pp_styles[i_text_length], pi_k_dates ? &pi_k_dates[i_text_length] : NULL, "\n", - GetStyleFromFontStack( p_sys, + GetStyleFromFontStack( p_filter, &p_fonts, i_style_flags ), i_k_date ); @@ -1550,7 +1869,7 @@ static int ProcessNodes( filter_t *p_filter, &pp_styles[i_text_length], pi_k_dates ? &pi_k_dates[i_text_length] : NULL, psz_node, - GetStyleFromFontStack( p_sys, + GetStyleFromFontStack( p_filter, &p_fonts, i_style_flags ), i_k_date ); @@ -1632,8 +1951,10 @@ static FT_Face LoadEmbeddedFace( filter_sys_t *p_sys, const text_style_t *p_styl { int i_style_received = ((p_face->style_flags & FT_STYLE_FLAG_BOLD) ? STYLE_BOLD : 0) | ((p_face->style_flags & FT_STYLE_FLAG_ITALIC ) ? STYLE_ITALIC : 0); - if( !strcasecmp( p_face->family_name, p_style->psz_fontname ) && - (p_style->i_style_flags & (STYLE_BOLD | STYLE_BOLD)) == i_style_received ) + if( p_face->family_name != NULL + && !strcasecmp( p_face->family_name, p_style->psz_fontname ) + && (p_style->i_style_flags & (STYLE_BOLD | STYLE_ITALIC)) + == i_style_received ) return p_face; FT_Done_Face( p_face ); @@ -1656,7 +1977,7 @@ static FT_Face LoadFace( filter_t *p_filter, if( !p_face ) { int i_idx = 0; - char *psz_fontfile; + char *psz_fontfile = NULL; #ifdef HAVE_FONTCONFIG psz_fontfile = FontConfig_Select( NULL, p_style->psz_fontname, @@ -1664,7 +1985,11 @@ static FT_Face LoadFace( filter_t *p_filter, (p_style->i_style_flags & STYLE_ITALIC) != 0, -1, &i_idx ); -#elif defined( WIN32 ) +#elif defined( __APPLE__ ) +#if !TARGET_OS_IPHONE + psz_fontfile = MacLegacy_Select( p_filter, p_style->psz_fontname, false, false, -1, &i_idx ); +#endif +#elif defined( _WIN32 ) psz_fontfile = Win32_Select( p_filter, p_style->psz_fontname, (p_style->i_style_flags & STYLE_BOLD) != 0, @@ -1759,15 +2084,22 @@ static int GetGlyph( filter_t *p_filter, if( p_filter->p_sys->p_stroker ) { outline = glyph; - FT_Glyph_StrokeBorder( &outline, p_filter->p_sys->p_stroker, 0, 0 ); + if( FT_Glyph_StrokeBorder( &outline, p_filter->p_sys->p_stroker, 0, 0 ) ) + outline = NULL; } FT_Glyph shadow = NULL; if( p_filter->p_sys->i_shadow_opacity > 0 ) { shadow = outline ? outline : glyph; - FT_Glyph_To_Bitmap( &shadow, FT_RENDER_MODE_NORMAL, p_pen_shadow, 0 ); - FT_Glyph_Get_CBox( shadow, ft_glyph_bbox_pixels, p_shadow_bbox ); + if( FT_Glyph_To_Bitmap( &shadow, FT_RENDER_MODE_NORMAL, p_pen_shadow, 0 ) ) + { + shadow = NULL; + } + else + { + FT_Glyph_Get_CBox( shadow, ft_glyph_bbox_pixels, p_shadow_bbox ); + } } *pp_shadow = shadow; @@ -1823,13 +2155,13 @@ static int ProcessLines( filter_t *p_filter, FT_BBox *p_bbox, int *pi_max_face_height, - uint32_t *psz_text, + uni_char_t *psz_text, text_style_t **pp_styles, uint32_t *pi_k_dates, int i_len ) { filter_sys_t *p_sys = p_filter->p_sys; - uint32_t *p_fribidi_string = NULL; + uni_char_t *p_fribidi_string = NULL; text_style_t **pp_fribidi_styles = NULL; int *p_new_positions = NULL; @@ -2007,7 +2339,9 @@ static int ProcessLines( filter_t *p_filter, msg_Err( p_filter, "Failed to set font size to %d", p_current_style->i_font_size ); if( p_sys->p_stroker ) { - int i_radius = (p_current_style->i_font_size << 6) * p_sys->f_outline_thickness; + double f_outline_thickness = var_InheritInteger( p_filter, "freetype-outline-thickness" ) / 100.0; + f_outline_thickness = VLC_CLIP( f_outline_thickness, 0.0, 0.5 ); + int i_radius = (p_current_style->i_font_size << 6) * f_outline_thickness; FT_Stroker_Set( p_sys->p_stroker, i_radius, FT_STROKER_LINECAP_ROUND, @@ -2025,7 +2359,7 @@ static int ProcessLines( filter_t *p_filter, while( i_part_length > 0 ) { const text_style_t *p_glyph_style = pp_styles[i_index]; - uint32_t character = psz_text[i_index]; + uni_char_t character = psz_text[i_index]; int i_glyph_index = FT_Get_Char_Index( p_current_face, character ); /* Get kerning vector */ @@ -2180,7 +2514,8 @@ static int ProcessLines( filter_t *p_filter, /* Update our baseline */ if( i_face_height_previous > 0 ) i_base_line += __MAX(i_face_height, i_face_height_previous); - i_face_height_previous = i_face_height; + if( i_face_height > 0 ) + i_face_height_previous = i_face_height; /* Update the line bbox with the actual base line */ if (line_bbox.yMax > line_bbox.yMin) { @@ -2194,6 +2529,7 @@ static int ProcessLines( filter_t *p_filter, { p_line->i_width = __MAX(line_bbox.xMax - line_bbox.xMin, 0); p_line->i_base_line = i_base_line; + p_line->i_height = __MAX(i_face_height, i_face_height_previous); if( i_ul_thickness > 0 ) { for( int i = 0; i < p_line->i_character_count; i++ ) @@ -2257,7 +2593,7 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, const size_t i_text_max = strlen( b_html ? p_region_in->psz_html : p_region_in->psz_text ); - uint32_t *psz_text = calloc( i_text_max, sizeof( *psz_text ) ); + uni_char_t *psz_text = calloc( i_text_max, sizeof( *psz_text ) ); text_style_t **pp_styles = calloc( i_text_max, sizeof( *pp_styles ) ); if( !psz_text || !pp_styles ) { @@ -2278,7 +2614,6 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, uint32_t *pi_k_durations = NULL; -#ifdef HAVE_STYLES if( b_html ) { stream_t *p_sub = stream_MemoryNew( VLC_OBJECT(p_filter), @@ -2336,12 +2671,12 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, stream_Delete( p_sub ); } else -#endif { text_style_t *p_style; if( p_region_in->p_style ) p_style = CreateStyle( p_region_in->p_style->psz_fontname, - p_region_in->p_style->i_font_size, + p_region_in->p_style->i_font_size > 0 ? p_region_in->p_style->i_font_size + : p_sys->i_font_size, (p_region_in->p_style->i_font_color & 0xffffff) | ((p_region_in->p_style->i_font_alpha & 0xff) << 24), 0x00ffffff, @@ -2350,11 +2685,15 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, STYLE_UNDERLINE | STYLE_STRIKEOUT) ); else + { + uint32_t i_font_color = var_InheritInteger( p_filter, "freetype-color" ); + i_font_color = VLC_CLIP( i_font_color, 0, 0xFFFFFF ); p_style = CreateStyle( p_sys->psz_fontfamily, p_sys->i_font_size, - (p_sys->i_font_color & 0xffffff) | + (i_font_color & 0xffffff) | ((p_sys->i_font_opacity & 0xff) << 24), 0x00ffffff, 0); + } if( p_sys->b_font_bold ) p_style->i_style_flags |= STYLE_BOLD; @@ -2387,7 +2726,9 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out, else if( !p_chroma_list || *p_chroma_list == 0 ) p_chroma_list = p_chroma_list_rgba; - const int i_margin = p_sys->i_background_opacity > 0 ? i_max_face_height / 4 : 0; + uint8_t i_background_opacity = var_InheritInteger( p_filter, "freetype-background-opacity" ); + i_background_opacity = VLC_CLIP( i_background_opacity, 0, 255 ); + const int i_margin = i_background_opacity > 0 ? i_max_face_height / 4 : 0; for( const vlc_fourcc_t *p_chroma = p_chroma_list; *p_chroma != 0; p_chroma++ ) { rv = VLC_EGENERIC; @@ -2437,8 +2778,6 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, return RenderCommon( p_filter, p_region_out, p_region_in, false, p_chroma_list ); } -#ifdef HAVE_STYLES - static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, subpicture_region_t *p_region_in, const vlc_fourcc_t *p_chroma_list ) @@ -2446,8 +2785,6 @@ static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, return RenderCommon( p_filter, p_region_out, p_region_in, true, p_chroma_list ); } -#endif - /***************************************************************************** * Create: allocates osd-text video thread output method ***************************************************************************** @@ -2459,7 +2796,9 @@ static int Create( vlc_object_t *p_this ) filter_sys_t *p_sys; char *psz_fontfile = NULL; char *psz_fontfamily = NULL; - int i_error = 0, fontindex = 0; + char *psz_monofontfile = NULL; + char *psz_monofontfamily = NULL; + int i_error = 0, fontindex = 0, monofontindex = 0; /* Allocate structure */ p_filter->p_sys = p_sys = malloc( sizeof(*p_sys) ); @@ -2467,48 +2806,44 @@ static int Create( vlc_object_t *p_this ) return VLC_ENOMEM; p_sys->psz_fontfamily = NULL; -#ifdef HAVE_STYLES p_sys->p_xml = NULL; -#endif p_sys->p_face = 0; p_sys->p_library = 0; p_sys->i_font_size = 0; p_sys->i_display_height = 0; - var_Create( p_filter, "freetype-rel-fontsize", - VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + /* + * The following variables should not be cached, as they might be changed on-the-fly: + * freetype-rel-fontsize, freetype-background-opacity, freetype-background-color, + * freetype-outline-thickness, freetype-color + * + */ psz_fontfamily = var_InheritString( p_filter, "freetype-font" ); + psz_monofontfamily = var_InheritString( p_filter, "freetype-monofont" ); p_sys->i_default_font_size = var_InheritInteger( p_filter, "freetype-fontsize" ); 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_InheritInteger( p_filter, "freetype-color" ); - p_sys->i_font_color = __MAX( __MIN( p_sys->i_font_color , 0xFFFFFF ), 0 ); + p_sys->i_font_opacity = VLC_CLIP( p_sys->i_font_opacity, 0, 255 ); p_sys->b_font_bold = var_InheritBool( p_filter, "freetype-bold" ); - p_sys->i_background_opacity = var_InheritInteger( p_filter,"freetype-background-opacity" );; - p_sys->i_background_opacity = __MAX( __MIN( p_sys->i_background_opacity, 255 ), 0 ); - p_sys->i_background_color = var_InheritInteger( p_filter, "freetype-background-color" ); - p_sys->i_background_color = __MAX( __MIN( p_sys->i_background_color, 0xFFFFFF ), 0 ); - - p_sys->f_outline_thickness = var_InheritInteger( p_filter, "freetype-outline-thickness" ) / 100.0; - p_sys->f_outline_thickness = __MAX( __MIN( p_sys->f_outline_thickness, 0.5 ), 0.0 ); + double f_outline_thickness = var_InheritInteger( p_filter, "freetype-outline-thickness" ) / 100.0; + f_outline_thickness = VLC_CLIP( f_outline_thickness, 0.0, 0.5 ); p_sys->i_outline_opacity = var_InheritInteger( p_filter, "freetype-outline-opacity" ); - p_sys->i_outline_opacity = __MAX( __MIN( p_sys->i_outline_opacity, 255 ), 0 ); + p_sys->i_outline_opacity = VLC_CLIP( p_sys->i_outline_opacity, 0, 255 ); p_sys->i_outline_color = var_InheritInteger( p_filter, "freetype-outline-color" ); - p_sys->i_outline_color = __MAX( __MIN( p_sys->i_outline_color, 0xFFFFFF ), 0 ); + p_sys->i_outline_color = VLC_CLIP( p_sys->i_outline_color, 0, 0xFFFFFF ); p_sys->i_shadow_opacity = var_InheritInteger( p_filter, "freetype-shadow-opacity" ); - p_sys->i_shadow_opacity = __MAX( __MIN( p_sys->i_shadow_opacity, 255 ), 0 ); + p_sys->i_shadow_opacity = VLC_CLIP( p_sys->i_shadow_opacity, 0, 255 ); p_sys->i_shadow_color = var_InheritInteger( p_filter, "freetype-shadow-color" ); - p_sys->i_shadow_color = __MAX( __MIN( p_sys->i_shadow_color, 0xFFFFFF ), 0 ); + p_sys->i_shadow_color = VLC_CLIP( p_sys->i_shadow_color, 0, 0xFFFFFF ); float f_shadow_angle = var_InheritFloat( p_filter, "freetype-shadow-angle" ); float f_shadow_distance = var_InheritFloat( p_filter, "freetype-shadow-distance" ); - f_shadow_distance = __MAX( __MIN( f_shadow_distance, 1 ), 0 ); + f_shadow_distance = VLC_CLIP( f_shadow_distance, 0, 1 ); p_sys->f_shadow_vector_x = f_shadow_distance * cos(2 * M_PI * f_shadow_angle / 360); p_sys->f_shadow_vector_y = f_shadow_distance * sin(2 * M_PI * f_shadow_angle / 360); -#ifdef WIN32 +#ifdef _WIN32 /* Get Windows Font folder */ wchar_t wdir[MAX_PATH]; if( S_OK != SHGetFolderPathW( NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, wdir ) ) @@ -2526,9 +2861,12 @@ static int Create( vlc_object_t *p_this ) #ifdef HAVE_STYLES psz_fontfamily = strdup( DEFAULT_FAMILY ); #else -# ifdef WIN32 +# ifdef _WIN32 if( asprintf( &psz_fontfamily, "%s"DEFAULT_FONT_FILE, p_sys->psz_win_fonts_path ) == -1 ) + { + psz_fontfamily = NULL; goto error; + } # else psz_fontfamily = strdup( DEFAULT_FONT_FILE ); # endif @@ -2545,7 +2883,14 @@ static int Create( vlc_object_t *p_this ) /* */ psz_fontfile = FontConfig_Select( NULL, psz_fontfamily, false, false, p_sys->i_default_font_size, &fontindex ); -#elif defined(WIN32) + psz_monofontfile = FontConfig_Select( NULL, psz_monofontfamily, false, + false, p_sys->i_default_font_size, + &monofontindex ); +#elif defined(__APPLE__) +#if !TARGET_OS_IPHONE + psz_fontfile = MacLegacy_Select( p_filter, psz_fontfamily, false, false, 0, &fontindex ); +#endif +#elif defined(_WIN32) psz_fontfile = Win32_Select( p_filter, psz_fontfamily, false, false, p_sys->i_default_font_size, &fontindex ); @@ -2555,11 +2900,15 @@ static int Create( vlc_object_t *p_this ) /* If nothing is found, use the default family */ if( !psz_fontfile ) psz_fontfile = strdup( psz_fontfamily ); + if( !psz_monofontfile ) + psz_monofontfile = strdup( psz_monofontfamily ); #else /* !HAVE_STYLES */ /* Use the default file */ psz_fontfile = psz_fontfamily; + psz_monofontfile = psz_monofontfamily; #endif + p_sys->psz_monofontfamily = psz_monofontfamily; /* */ i_error = FT_Init_FreeType( &p_sys->p_library ); @@ -2584,9 +2933,6 @@ static int Create( vlc_object_t *p_this ) psz_fontfile ? psz_fontfile : "(null)" ); goto error; } -#ifdef HAVE_STYLES - free( psz_fontfile ); -#endif i_error = FT_Select_Charmap( p_sys->p_face, ft_encoding_unicode ); if( i_error ) @@ -2598,7 +2944,7 @@ static int Create( vlc_object_t *p_this ) if( SetFontSize( p_filter, 0 ) != VLC_SUCCESS ) goto error; p_sys->p_stroker = NULL; - if( p_sys->f_outline_thickness > 0.001 ) + if( f_outline_thickness > 0.001 ) { i_error = FT_Stroker_New( p_sys->p_library, &p_sys->p_stroker ); if( i_error ) @@ -2609,14 +2955,15 @@ static int Create( vlc_object_t *p_this ) p_sys->i_font_attachments = 0; p_filter->pf_render_text = RenderText; -#ifdef HAVE_STYLES p_filter->pf_render_html = RenderHtml; -#else - p_filter->pf_render_html = NULL; -#endif LoadFontsFromAttachments( p_filter ); +#ifdef HAVE_STYLES + free( psz_fontfile ); + free( psz_monofontfile ); +#endif + return VLC_SUCCESS; error: @@ -2624,8 +2971,10 @@ error: if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library ); #ifdef HAVE_STYLES free( psz_fontfile ); + free( psz_monofontfile ); #endif free( psz_fontfamily ); + free( psz_monofontfamily ); free( p_sys ); return VLC_EGENERIC; } @@ -2648,10 +2997,13 @@ static void Destroy( vlc_object_t *p_this ) free( p_sys->pp_font_attachments ); } -#ifdef HAVE_STYLES if( p_sys->p_xml ) xml_ReaderDelete( p_sys->p_xml ); -#endif free( p_sys->psz_fontfamily ); + free( p_sys->psz_monofontfamily ); + +#ifdef _WIN32 + free( p_sys->psz_win_fonts_path ); +#endif /* FcFini asserts calling the subfunction FcCacheFini() * even if no other library functions have been made since FcInit(), @@ -2663,5 +3015,3 @@ static void Destroy( vlc_object_t *p_this ) FT_Done_FreeType( p_sys->p_library ); free( p_sys ); } - -