]> git.sesse.net Git - vlc/blobdiff - modules/text_renderer/freetype.c
introduce VLC_CLIP() macro to replace use pair of __MAX() and __MIN()
[vlc] / modules / text_renderer / freetype.c
index 5eac887dc575a997dcfb870f0aa2b355f9c45dfd..b60b186ed9398c1143232841472dac18d3b04460 100644 (file)
@@ -108,7 +108,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. " )
@@ -187,46 +187,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" );
@@ -256,7 +256,7 @@ typedef struct
 typedef struct line_desc_t line_desc_t;
 struct line_desc_t
 {
-    line_desc_t    *p_next;
+    line_desc_t      *p_next;
 
     int              i_width;
     int              i_base_line;
@@ -545,7 +545,10 @@ static int GetFileFontByName( const char *font_name, char **psz_filename )
     wchar_t vbuffer[MAX_PATH];
     wchar_t dbuffer[256];
 
-    if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, FONT_DIR_NT, 0, KEY_READ, &hKey) != ERROR_SUCCESS )
+    size_t fontname_len = strlen( font_name );
+
+    if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, FONT_DIR_NT, 0, KEY_READ, &hKey)
+            != ERROR_SUCCESS )
         return 1;
 
     for( int index = 0;; index++ )
@@ -553,9 +556,10 @@ static int GetFileFontByName( const char *font_name, char **psz_filename )
         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 = RegEnumValueW( hKey, index, vbuffer, &vbuflen,
+                                       NULL, NULL, (LPBYTE)dbuffer, &dbuflen);
+        if( i_result != ERROR_SUCCESS )
+            return i_result;
 
         char *psz_value = FromWide( vbuffer );
 
@@ -568,7 +572,7 @@ static int GetFileFontByName( const char *font_name, char **psz_filename )
                 break;
         }
         else {
-            if( strcasecmp( psz_value, font_name ) == 0 )
+            if( strncasecmp( psz_value, font_name, fontname_len ) == 0 )
                 break;
         }
     }
@@ -592,7 +596,9 @@ 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( strlen( family ) < 1 )
+        goto fail;
 
     /* */
     LOGFONT lf;
@@ -609,21 +615,40 @@ 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 )
-        return NULL;
-
-    /* FIXME: increase i_idx, when concatenated strings  */
-    i_idx = 0;
-
     /* */
-    char *psz_tmp;
-    if( asprintf( &psz_tmp, "%s\\%s", p_filter->p_sys->psz_win_fonts_path, psz_filename ) == -1 )
-        return NULL;
-    return psz_tmp;
+    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
+#endif /* HAVE_WIN32 */
 
-#endif
+#endif /* HAVE_STYLES */
 
 
 /*****************************************************************************
@@ -694,7 +719,7 @@ static int RenderYUVP( filter_t *p_filter, subpicture_region_t *p_region,
     for( ; p_line != NULL; p_line = p_line->p_next )
     {
         int i_align_left = 0;
-        if( p_line->i_width < fmt.i_visible_width )
+        if( p_line->i_width < (int)fmt.i_visible_width )
         {
             if( (p_region->i_align & 0x3) == SUBPICTURE_ALIGN_RIGHT )
                 i_align_left = ( fmt.i_visible_width - p_line->i_width );
@@ -1453,7 +1478,8 @@ static int ProcessNodes( filter_t *p_filter,
     {
         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) |
@@ -1633,7 +1659,7 @@ 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 )
+                    (p_style->i_style_flags & (STYLE_BOLD | STYLE_ITALIC)) == i_style_received )
                     return p_face;
 
                 FT_Done_Face( p_face );
@@ -1759,15 +1785,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;
 
@@ -2107,7 +2140,7 @@ static int ProcessLines( filter_t *p_filter,
                     BBoxEnlarge( &line_bbox_new, &shadow_bbox );
 
                 b_break_line = i_index > i_start &&
-                               line_bbox_new.xMax - line_bbox_new.xMin >= p_filter->fmt_out.video.i_visible_width;
+                               line_bbox_new.xMax - line_bbox_new.xMin >= (int)p_filter->fmt_out.video.i_visible_width;
                 if( b_break_line )
                 {
                     FT_Done_Glyph( glyph );
@@ -2180,7 +2213,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) {
@@ -2218,7 +2252,7 @@ static int ProcessLines( filter_t *p_filter,
         if( i_start < i_len && psz_text[i_start] == '\n' )
             i_start++;
 
-        if( bbox.yMax - bbox.yMin >= p_filter->fmt_out.video.i_visible_height )
+        if( bbox.yMax - bbox.yMin >= (int)p_filter->fmt_out.video.i_visible_height )
         {
             msg_Err( p_filter, "Truncated too high subtitle" );
             break;
@@ -2341,7 +2375,8 @@ static int RenderCommon( filter_t *p_filter, subpicture_region_t *p_region_out,
         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,
@@ -2481,30 +2516,30 @@ static int Create( vlc_object_t *p_this )
     psz_fontfamily = var_InheritString( p_filter, "freetype-font" );
     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_opacity = VLC_CLIP( p_sys->i_font_opacity, 0, 255 );
     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_color = VLC_CLIP( p_sys->i_font_color, 0, 0xFFFFFF );
     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_opacity = VLC_CLIP( p_sys->i_background_opacity, 0, 255 );
     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->i_background_color = VLC_CLIP( p_sys->i_background_color, 0, 0xFFFFFF );
 
     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 );
+    p_sys->f_outline_thickness = VLC_CLIP( p_sys->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);
 
@@ -2584,9 +2619,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 )
@@ -2617,6 +2649,10 @@ static int Create( vlc_object_t *p_this )
 
     LoadFontsFromAttachments( p_filter );
 
+#ifdef HAVE_STYLES
+    free( psz_fontfile );
+#endif
+
     return VLC_SUCCESS;
 
 error: