]> git.sesse.net Git - vlc/blobdiff - modules/misc/freetype.c
* src/video_output/vout_subpictures.c : New OSD channels
[vlc] / modules / misc / freetype.c
index 66fbfe06f27d2d46af77c9c7193aa2d2c7a39347..1a2078307d4b9a4dd6f4336ffe285f069905319d 100644 (file)
@@ -2,7 +2,7 @@
  * freetype.c : Put text on the video, using freetype2
  *****************************************************************************
  * Copyright (C) 2002, 2003 VideoLAN
- * $Id: freetype.c,v 1.34 2003/11/19 13:25:48 hartman Exp $
+ * $Id$
  *
  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
  *
 #include <stdlib.h>                                      /* malloc(), free() */
 #include <string.h>
 
+#ifdef HAVE_LINUX_LIMITS_H
+#   include <linux/limits.h>
+#endif
+
 #include <vlc/vlc.h>
 #include <vlc/vout.h>
 #include <osd.h>
@@ -73,8 +77,9 @@ static void RenderYUY2( vout_thread_t *, picture_t *,
                         const subpicture_t * );
 static void RenderRV32( vout_thread_t *, picture_t *,
                         const subpicture_t * );
-static int  AddText   ( vout_thread_t *, byte_t *, text_style_t *, int,
-                        int, int, mtime_t, mtime_t );
+static subpicture_t *AddText ( vout_thread_t *, int, char *, text_style_t *,
+                               int, int, int, mtime_t, mtime_t );
+
 static void FreeString( subpicture_t * );
 
 #if !defined(HAVE_ICONV)
@@ -87,25 +92,29 @@ static line_desc_t *NewLine( byte_t * );
  * Module descriptor
  *****************************************************************************/
 #define FONT_TEXT N_("Font")
-#define FONT_LONGTEXT N_("Filename of Font")
+#define FONT_LONGTEXT N_("Font filename")
 #define FONTSIZE_TEXT N_("Font size in pixels")
-#define FONTSIZE_LONGTEXT N_("The size of the fonts used by the osd module. If \
- set to something different than 0 this option will override the relative font size " )
+#define FONTSIZE_LONGTEXT N_("The size of the fonts used by the osd module. " \
+    "If set to something different than 0 this option will override the " \
+    "relative font size " )
 #define FONTSIZER_TEXT N_("Font size")
 #define FONTSIZER_LONGTEXT N_("The size of the fonts used by the osd module" )
 
-static int  *pi_sizes[] = { 20, 18, 16, 12, 6 };
+static int   pi_sizes[] = { 20, 18, 16, 12, 6 };
 static char *ppsz_sizes_text[] = { N_("Smaller"), N_("Small"), N_("Normal"),
                                    N_("Large"), N_("Larger") };
 
 vlc_module_begin();
-    add_category_hint( N_("Fonts"), NULL, VLC_FALSE );
-    add_file( "freetype-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, VLC_FALSE );
-    add_integer( "freetype-fontsize", 0, NULL, FONTSIZE_TEXT, FONTSIZE_LONGTEXT, VLC_TRUE );
-    add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT, FONTSIZER_LONGTEXT,
-                 VLC_FALSE );
-        change_integer_list( pi_sizes, ppsz_sizes_text, 0 );
     set_description( _("freetype2 font renderer") );
+
+    add_file( "freetype-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT,
+              VLC_FALSE );
+    add_integer( "freetype-fontsize", 0, NULL, FONTSIZE_TEXT,
+                 FONTSIZE_LONGTEXT, VLC_TRUE );
+    add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT,
+                 FONTSIZER_LONGTEXT, VLC_FALSE );
+        change_integer_list( pi_sizes, ppsz_sizes_text, 0 );
+
     set_capability( "text renderer", 100 );
     add_shortcut( "text" );
     set_callbacks( Create, Destroy );
@@ -250,7 +259,7 @@ static int Create( vlc_object_t *p_this )
         FT_HAS_KERNING(p_vout->p_text_renderer_data->p_face);
 
     var_Get( p_vout, "freetype-fontsize", &val );
-    
+
     if( val.i_int )
     {
         i_fontsize = val.i_int;
@@ -329,26 +338,25 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic,
  * Draw a string on a i420 (or similar) picture
  */
 static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
-                    const subpicture_t *p_subpic )
+                        const subpicture_t *p_subpic )
 {
     subpicture_sys_t *p_string = p_subpic->p_sys;
     int i_plane, x, y, pen_x, pen_y;
     unsigned int i;
     line_desc_t *p_line;
 
-    for( p_line = p_subpic->p_sys->p_lines; p_line != NULL; p_line = p_line->p_next )
+    for( p_line = p_subpic->p_sys->p_lines; p_line != NULL;
+         p_line = p_line->p_next )
     {
-        for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ )
+        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
         {
-            uint8_t *p_in;
+            uint8_t *p_in = p_pic->p[ i_plane ].p_pixels;
             int i_pic_pitch = p_pic->p[ i_plane ].i_pitch;
             int i_pic_width = p_pic->p[ i_plane ].i_visible_pitch;
 
-            p_in = p_pic->p[ i_plane ].p_pixels;
-
-            if ( i_plane == 0 )
+            if( i_plane == 0 )
             {
-                if ( p_string->i_flags & OSD_ALIGN_BOTTOM )
+                if( p_string->i_flags & OSD_ALIGN_BOTTOM )
                 {
                     pen_y = p_pic->p[ i_plane ].i_lines - p_string->i_height -
                         p_string->i_y_margin;
@@ -358,12 +366,13 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
                     pen_y = p_string->i_y_margin;
                 }
                 pen_y += p_vout->p_text_renderer_data->p_face->size->metrics.ascender >> 6;
-                if ( p_string->i_flags & OSD_ALIGN_RIGHT )
+
+                if( p_string->i_flags & OSD_ALIGN_RIGHT )
                 {
                     pen_x = i_pic_width - p_line->i_width
                         - p_string->i_x_margin;
                 }
-                else if ( p_string->i_flags & OSD_ALIGN_LEFT )
+                else if( p_string->i_flags & OSD_ALIGN_LEFT )
                 {
                     pen_x = p_string->i_x_margin;
                 }
@@ -376,30 +385,49 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
                 for( i = 0; p_line->pp_glyphs[i] != NULL; i++ )
                 {
                     FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ];
-#define alpha p_vout->p_text_renderer_data->pi_gamma[ p_glyph->bitmap.buffer[ x + y * p_glyph->bitmap.width ] ]
-#define pixel p_in[ ( p_line->p_glyph_pos[ i ].y + pen_y + y - p_glyph->top ) * i_pic_pitch + x + pen_x + p_line->p_glyph_pos[ i ].x + p_glyph->left ]
-                    for(y = 0; y < p_glyph->bitmap.rows; y++ )
+                    int i_alpha_offset = -1;
+                    int i_offset = ( p_line->p_glyph_pos[ i ].y + pen_y -
+                                     p_glyph->top ) * i_pic_pitch +
+                                   p_line->p_glyph_pos[ i ].x + p_glyph->left;
+
+#define alpha p_vout->p_text_renderer_data->pi_gamma[ p_glyph->bitmap.buffer[ i_alpha_offset ] ]
+#define pixel p_in[ i_offset + x + pen_x ]
+
+                    for( y = 0; y < p_glyph->bitmap.rows; y++ )
                     {
                         for( x = 0; x < p_glyph->bitmap.width; x++ )
                         {
-                            pen_y--;
+                            i_alpha_offset++;
+                            if( alpha == 0 ) continue;
+
+                            pen_y--; i_offset -= i_pic_pitch;
                             pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                            pen_y++; pen_x--;
+                            pen_y++; i_offset += i_pic_pitch; pen_x--;
                             pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
                             pen_x += 2;
                             pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                            pen_y++; pen_x--;
+                            pen_y++; i_offset += i_pic_pitch; pen_x--;
                             pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
-                            pen_y--;
+                            pen_y--; i_offset -= i_pic_pitch;
                         }
+                        i_offset += i_pic_pitch;
                     }
-                    for(y = 0; y < p_glyph->bitmap.rows; y++ )
+
+                    i_alpha_offset = -1;
+                    i_offset = ( p_line->p_glyph_pos[ i ].y + pen_y -
+                                 p_glyph->top ) * i_pic_pitch +
+                               p_line->p_glyph_pos[ i ].x + p_glyph->left;
+                    for( y = 0; y < p_glyph->bitmap.rows; y++ )
                     {
                         for( x = 0; x < p_glyph->bitmap.width; x++ )
                         {
+                            i_alpha_offset++;
+                            if( alpha == 0 ) continue;
+
                             pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 ) +
                                 ( 255 * alpha >> 8 );
                         }
+                        i_offset += i_pic_pitch;
                     }
 #undef alpha
 #undef pixel
@@ -409,8 +437,8 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
             {
                 if ( p_string->i_flags & OSD_ALIGN_BOTTOM )
                 {
-                    pen_y = p_pic->p[i_plane].i_lines - ( p_string->i_height>>1) -
-                        (p_string->i_y_margin>>1);
+                    pen_y = p_pic->p[i_plane].i_lines - (p_string->i_height>>1)
+                        (p_string->i_y_margin>>1);
                 }
                 else
                 {
@@ -441,6 +469,8 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
                     {
                         for( x = 0; x < p_glyph->bitmap.width; x+=2 )
                         {
+                            if( alpha == 0 ) continue;
+
                             pixel = ( ( pixel * ( 0xFF - alpha ) ) >> 8 ) +
                                 ( 0x80 * alpha >> 8 );
 #undef alpha
@@ -472,7 +502,7 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
         int i_pic_width = p_pic->p[0].i_visible_pitch;
 
         p_in = p_pic->p[0].p_pixels;
-        
+
         if ( p_string->i_flags & OSD_ALIGN_BOTTOM )
         {
             pen_y = p_pic->p[0].i_lines - p_string->i_height -
@@ -496,7 +526,7 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
         {
             pen_x = i_pic_width / 2 /2 - p_line->i_width / 2 + p_string->i_x_margin;
         }
-        
+
         for( i = 0; p_line->pp_glyphs[i] != NULL; i++ )
         {
             FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ];
@@ -506,6 +536,8 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
             {
                 for( x = 0; x < p_glyph->bitmap.width; x++ )
                 {
+                    if( alpha == 0 ) continue;
+
                     pen_y--;
                     pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
                     pen_y++; pen_x--;
@@ -521,6 +553,8 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
             {
                 for( x = 0; x < p_glyph->bitmap.width; x++ )
                 {
+                    if( alpha == 0 ) continue;
+
                     pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 ) +
                         ( 255 * alpha >> 8 );
                 }
@@ -543,7 +577,7 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
     line_desc_t *p_line;
 
     i_plane = 0;
-    
+
     for( p_line = p_subpic->p_sys->p_lines; p_line != NULL; p_line = p_line->p_next )
     {
         uint8_t *p_in;
@@ -551,7 +585,7 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
         int i_pic_width = p_pic->p[ i_plane ].i_visible_pitch;
 
         p_in = p_pic->p[ i_plane ].p_pixels;
-        
+
         if ( p_string->i_flags & OSD_ALIGN_BOTTOM )
         {
             pen_y = p_pic->p[ i_plane ].i_lines - p_string->i_height -
@@ -576,7 +610,7 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
             pen_x = i_pic_width / 2 / 4 - p_line->i_width / 2
                 + p_string->i_x_margin;
         }
-        
+
         for( i = 0; p_line->pp_glyphs[i] != NULL; i++ )
         {
             FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ];
@@ -586,6 +620,8 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
             {
                 for( x = 0; x < p_glyph->bitmap.width; x++ )
                 {
+                    if( alpha == 0 ) continue;
+
                     pen_y--;
                     pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 );
                     pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 );
@@ -609,6 +645,8 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
             {
                 for( x = 0; x < p_glyph->bitmap.width; x++ )
                 {
+                    if( alpha == 0 ) continue;
+
                     pixel( 0 ) = ( ( pixel( 0 ) * ( 255 - alpha ) ) >> 8 ) +
                         ( 255 * alpha >> 8 );
                     pixel( 1 ) = ( ( pixel( 1 ) * ( 255 - alpha ) ) >> 8 ) +
@@ -629,9 +667,10 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
  * needed glyphs into memory. It is used as pf_add_string callback in
  * the vout method by this module
  */
-static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
-                     text_style_t *p_style, int i_flags, int i_hmargin,
-                     int i_vmargin, mtime_t i_start, mtime_t i_stop )
+static subpicture_t *AddText ( vout_thread_t *p_vout, int i_channel,
+                     char *psz_string, text_style_t *p_style, int i_flags,
+                     int i_hmargin, int i_vmargin, mtime_t i_start,
+                     mtime_t i_stop )
 {
     subpicture_sys_t *p_string;
     int i, i_pen_y, i_pen_x, i_error, i_glyph_index, i_previous;
@@ -639,8 +678,11 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
     line_desc_t  *p_line,  *p_next;
     uint32_t *p_unicode_string, i_char;
     int i_string_length;
+
+#if defined(HAVE_ICONV)
     iconv_t iconv_handle;
-    
+#endif
+
     FT_BBox line;
     FT_BBox glyph_size;
     FT_Vector result;
@@ -649,7 +691,7 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
     /* Sanity check */
     if ( !psz_string || !*psz_string )
     {
-        return VLC_EGENERIC;
+        return NULL;
     }
 
     result.x = 0;
@@ -664,10 +706,10 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
     p_subpic = 0;
 
     /* Create and initialize a subpicture */
-    p_subpic = vout_CreateSubPicture( p_vout, MEMORY_SUBPICTURE );
+    p_subpic = vout_CreateSubPicture( p_vout, i_channel, MEMORY_SUBPICTURE );
     if ( p_subpic == NULL )
     {
-        return VLC_EGENERIC;
+        return NULL;
     }
     p_subpic->p_sys = 0;
     p_subpic->pf_render = Render;
@@ -706,7 +748,7 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
     }
 #if defined(WORDS_BIGENDIAN)
     iconv_handle = iconv_open( "UCS-4BE", "UTF-8" );
-#else    
+#else
     iconv_handle = iconv_open( "UCS-4LE", "UTF-8" );
 #endif
     if( iconv_handle == (iconv_t)-1 )
@@ -732,7 +774,7 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
         *(uint32_t*)p_out_buffer = 0;
         i_string_length = ( i_out_bytes - i_out_bytes_left ) / sizeof(uint32_t);
     }
-        
+
 #if defined(HAVE_FRIBIDI)
     {
         uint32_t *p_fribidi_string;
@@ -747,7 +789,7 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
     }
 #endif
 #endif
-    
+
     /* Calculate relative glyph positions and a bounding box for the
      * entire string */
     p_line = NewLine( psz_string );
@@ -846,7 +888,7 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
     p_string->i_height = result.y;
     p_string->i_width = result.x;
     vout_DisplaySubPicture( p_vout, p_subpic );
-    return VLC_SUCCESS;
+    return p_subpic;
 
 #undef face
 #undef glyph
@@ -854,7 +896,7 @@ static int AddText ( vout_thread_t *p_vout, byte_t *psz_string,
  error:
     FreeString( p_subpic );
     vout_DestroySubPicture( p_vout, p_subpic );
-    return VLC_EGENERIC;
+    return NULL;
 }
 
 static void FreeString( subpicture_t *p_subpic )
@@ -876,7 +918,7 @@ static void FreeString( subpicture_t *p_subpic )
         free( p_line->p_glyph_pos );
         free( p_line );
     }
-            
+
     free( p_string->psz_text );
     free( p_string );
 }