* 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>
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)
* 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 );
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;
* 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;
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;
}
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
{
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
{
{
for( x = 0; x < p_glyph->bitmap.width; x+=2 )
{
+ if( alpha == 0 ) continue;
+
pixel = ( ( pixel * ( 0xFF - alpha ) ) >> 8 ) +
( 0x80 * alpha >> 8 );
#undef alpha
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 -
{
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 ];
{
for( x = 0; x < p_glyph->bitmap.width; x++ )
{
+ if( alpha == 0 ) continue;
+
pen_y--;
pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 );
pen_y++; pen_x--;
{
for( x = 0; x < p_glyph->bitmap.width; x++ )
{
+ if( alpha == 0 ) continue;
+
pixel = ( ( pixel * ( 255 - alpha ) ) >> 8 ) +
( 255 * alpha >> 8 );
}
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;
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 -
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 ];
{
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 );
{
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 ) +
* 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;
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;
/* Sanity check */
if ( !psz_string || !*psz_string )
{
- return VLC_EGENERIC;
+ return NULL;
}
result.x = 0;
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;
}
#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 )
*(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;
}
#endif
#endif
-
+
/* Calculate relative glyph positions and a bounding box for the
* entire string */
p_line = NewLine( 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
error:
FreeString( p_subpic );
vout_DestroySubPicture( p_vout, p_subpic );
- return VLC_EGENERIC;
+ return NULL;
}
static void FreeString( subpicture_t *p_subpic )
free( p_line->p_glyph_pos );
free( p_line );
}
-
+
free( p_string->psz_text );
free( p_string );
}