X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Ffreetype.c;h=7b2a35cb0f60593166e382e75ed68241e3c3b1b0;hb=becc54dc00c7ae782712ba2acd3bc0e933809d08;hp=d6fac92745bc20a40357bf248c769c4349c02cf1;hpb=247630124b19091ad41aca27afce77dd90d2b534;p=vlc diff --git a/modules/misc/freetype.c b/modules/misc/freetype.c index d6fac92745..7b2a35cb0f 100644 --- a/modules/misc/freetype.c +++ b/modules/misc/freetype.c @@ -71,10 +71,12 @@ static int Create ( vlc_object_t * ); static void Destroy( vlc_object_t * ); /* The RenderText call maps to pf_render_string, defined in vlc_filter.h */ -static subpicture_region_t *RenderText( filter_t *, subpicture_t *, - subpicture_region_t* ); +static int RenderText( filter_t *, subpicture_region_t *, + subpicture_region_t * ); static line_desc_t *NewLine( byte_t * ); +static int SetFontSize( filter_t *, int ); + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -85,11 +87,12 @@ static line_desc_t *NewLine( byte_t * ); "If set to something different than 0 this option will override the " \ "relative font size " ) #define OPACITY_TEXT N_("Opacity, 0..255") -#define OPACITY_LONGTEXT N_("The opacity (inverse of transparency) of overlay text. " \ - "1 = transparent, 255 = totally opaque. " ) +#define OPACITY_LONGTEXT N_("The opacity (inverse of transparency) of " \ + "overlay text. 0 = transparent, 255 = totally opaque. " ) #define COLOR_TEXT N_("Text Default Color") -#define COLOR_LONGTEXT N_("The color of overlay text. 1 byte for each color, hexadecimal." \ - "#000000 = all colors off, 0xFF0000 = just Red, 0xFFFFFF = all color on [White]" ) +#define COLOR_LONGTEXT N_("The color of overlay text. 1 byte for each color, "\ + "hexadecimal. #000000 = all colors off, 0xFF0000 = just Red, " \ + "0xFFFFFF = all color on [White]" ) #define FONTSIZER_TEXT N_("Font size") #define FONTSIZER_LONGTEXT N_("The size of the fonts used by the osd module" ) @@ -107,10 +110,10 @@ static char *ppsz_color_descriptions[] = { N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"), N_("Aqua") }; vlc_module_begin(); - set_shortname( _("Freetype")); + set_shortname( _("Text renderer")); set_description( _("Freetype2 font renderer") ); set_category( CAT_VIDEO ); - set_subcategory( SUBCAT_VIDEO_TEXT ); + set_subcategory( SUBCAT_VIDEO_SUBPIC ); add_file( "freetype-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, VLC_FALSE ); @@ -120,11 +123,11 @@ vlc_module_begin(); /* opacity valid on 0..255, with default 255 = fully opaque */ add_integer_with_range( "freetype-opacity", 255, 0, 255, NULL, - OPACITY_TEXT, OPACITY_LONGTEXT, VLC_FALSE ); + OPACITY_TEXT, OPACITY_LONGTEXT, VLC_TRUE ); /* hook to the color values list, with default 0x00ffffff = white */ add_integer( "freetype-color", 0x00FFFFFF, NULL, COLOR_TEXT, - COLOR_LONGTEXT, VLC_TRUE ); + COLOR_LONGTEXT, VLC_FALSE ); change_integer_list( pi_color_values, ppsz_color_descriptions, 0 ); add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT, @@ -136,32 +139,23 @@ vlc_module_begin(); set_callbacks( Create, Destroy ); vlc_module_end(); -/** - * Private data in a subpicture. Describes a string. - */ -typedef struct subpicture_data_t -{ - int i_width; - int i_height; - /** The string associated with this subpicture */ - byte_t *psz_text; - line_desc_t *p_lines; - -} subpicture_data_t; - struct line_desc_t { /** NULL-terminated list of glyphs making the string */ FT_BitmapGlyph *pp_glyphs; /** list of relative positions for the glyphs */ FT_Vector *p_glyph_pos; + int i_height; int i_width; + int i_red, i_green, i_blue; + int i_alpha; + line_desc_t *p_next; }; -static subpicture_region_t *Render( filter_t *, subpicture_t *, subpicture_data_t *, uint8_t, int, int, int ); -static void FreeString( subpicture_data_t * ); +static int Render( filter_t *, subpicture_region_t *, line_desc_t *, int, int); +static void FreeLines( line_desc_t * ); static void FreeLine( line_desc_t * ); /***************************************************************************** @@ -175,12 +169,12 @@ struct filter_sys_t FT_Library p_library; /* handle to library */ FT_Face p_face; /* handle to face object */ vlc_bool_t i_use_kerning; - uint8_t i_font_opacity; /* freetype-opacity */ - int i_font_color; /* freetype-color */ - int i_red, i_blue, i_green; /* function vars to render */ + uint8_t i_font_opacity; + int i_font_color; int i_font_size; - uint8_t i_opacity; /* function var to render */ - uint8_t pi_gamma[256]; + + int i_default_font_size; + int i_display_height; }; /***************************************************************************** @@ -193,11 +187,11 @@ static int Create( vlc_object_t *p_this ) filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; char *psz_fontfile = NULL; - int i, i_error; + int i_error; vlc_value_t val; /* Allocate structure */ - p_sys = malloc( sizeof( filter_sys_t ) ); + p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) { msg_Err( p_filter, "out of memory" ); @@ -206,9 +200,7 @@ static int Create( vlc_object_t *p_this ) p_sys->p_face = 0; p_sys->p_library = 0; p_sys->i_font_size = 0; - - for( i = 0; i < 256; i++ ) p_sys->pi_gamma[i] = i + (256 - i) / 16; - p_sys->pi_gamma[0] = 0; + p_sys->i_display_height = 0; var_Create( p_filter, "freetype-font", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); @@ -223,11 +215,7 @@ static int Create( vlc_object_t *p_this ) var_Create( p_filter, "freetype-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_filter, "freetype-color", &val ); - if( ( val.i_int > -1 ) && ( val.i_int < 0x01000000 ) ) /* valid range */ - { - p_sys->i_font_color = val.i_int; - } - else msg_Warn(p_filter, "Invalid freetype color specified, using white [0xFFFFFF]"); + p_sys->i_font_color = __MAX( __MIN( val.i_int, 0xFFFFFF ), 0 ); /* Look what method was requested */ var_Get( p_filter, "freetype-font", &val ); @@ -276,34 +264,12 @@ static int Create( vlc_object_t *p_this ) p_sys->i_use_kerning = FT_HAS_KERNING( p_sys->p_face ); - var_Get( p_filter, "freetype-fontsize", &val ); - if( val.i_int ) - { - p_sys->i_font_size = val.i_int; - } - else - { - var_Get( p_filter, "freetype-rel-fontsize", &val ); - p_sys->i_font_size = (int)p_filter->fmt_out.video.i_height / val.i_int; - } - if( p_sys->i_font_size <= 0 ) - { - msg_Warn( p_filter, "Invalid fontsize, using 12" ); - p_sys->i_font_size = 12; - } - msg_Dbg( p_filter, "Using fontsize: %i", p_sys->i_font_size); - - i_error = FT_Set_Pixel_Sizes( p_sys->p_face, 0, p_sys->i_font_size ); - if( i_error ) - { - msg_Err( p_filter, "couldn't set font size to %d", p_sys->i_font_size ); - goto error; - } + p_sys->i_default_font_size = val.i_int; + if( SetFontSize( p_filter, 0 ) != VLC_SUCCESS ) goto error; if( psz_fontfile ) free( psz_fontfile ); - p_filter->pf_render_string = RenderText; - p_filter->p_sys = p_sys; + p_filter->pf_render_text = RenderText; return VLC_SUCCESS; error: @@ -334,136 +300,152 @@ static void Destroy( vlc_object_t *p_this ) ***************************************************************************** * This function merges the previously rendered freetype glyphs into a picture *****************************************************************************/ -static subpicture_region_t *Render( filter_t *p_filter, subpicture_t *p_spu, - subpicture_data_t *p_string, - uint8_t opacity, - int red, int green, int blue) +static int Render( filter_t *p_filter, subpicture_region_t *p_region, + line_desc_t *p_line, int i_width, int i_height ) { - filter_sys_t *p_sys = p_filter->p_sys; - line_desc_t *p_line; - uint8_t *p_y, *p_u, *p_v, *p_a; + static uint8_t pi_gamma[16] = + {0x00, 0x41, 0x52, 0x63, 0x84, 0x85, 0x96, 0xa7, 0xb8, 0xc9, + 0xca, 0xdb, 0xdc, 0xed, 0xee, 0xff}; + + uint8_t *p_dst; video_format_t fmt; int i, x, y, i_pitch; - uint8_t i_y, i_u, i_v; /* YUV values, derived from incoming RGB */ - subpicture_region_t *p_region; - - /* Calculate text color components */ - i_y = (uint8_t)(( 66 * red + 129 * green + 25 * blue + 128) >> 8) + 16; - i_u = (uint8_t)(( -38 * red - 74 * green + 112 * blue + 128) >> 8) + 128; - i_v = (uint8_t)(( 112 * red - 94 * green - 18 * blue + 128) >> 8) + 128; + uint8_t i_y; /* YUV values, derived from incoming RGB */ + int8_t i_u, i_v; + subpicture_region_t *p_region_tmp; /* Create a new subpicture region */ memset( &fmt, 0, sizeof(video_format_t) ); - fmt.i_chroma = VLC_FOURCC('Y','U','V','A'); - fmt.i_aspect = VOUT_ASPECT_FACTOR; - fmt.i_width = fmt.i_visible_width = p_string->i_width + 2; - fmt.i_height = fmt.i_visible_height = p_string->i_height + 2; + fmt.i_chroma = VLC_FOURCC('Y','U','V','P'); + fmt.i_aspect = 0; + fmt.i_width = fmt.i_visible_width = i_width + 4; + fmt.i_height = fmt.i_visible_height = i_height + 4; fmt.i_x_offset = fmt.i_y_offset = 0; - p_region = p_spu->pf_create_region( VLC_OBJECT(p_filter), &fmt ); - if( !p_region ) + p_region_tmp = spu_CreateRegion( p_filter, &fmt ); + if( !p_region_tmp ) { msg_Err( p_filter, "cannot allocate SPU region" ); - return NULL; + return VLC_EGENERIC; } - p_region->i_x = p_region->i_y = 0; - p_y = p_region->picture.Y_PIXELS; - p_u = p_region->picture.U_PIXELS; - p_v = p_region->picture.V_PIXELS; - p_a = p_region->picture.A_PIXELS; + p_region->fmt = p_region_tmp->fmt; + p_region->picture = p_region_tmp->picture; + free( p_region_tmp ); + + /* Calculate text color components */ + i_y = (uint8_t)(( 66 * p_line->i_red + 129 * p_line->i_green + + 25 * p_line->i_blue + 128) >> 8) + 16; + i_u = (int8_t)(( -38 * p_line->i_red - 74 * p_line->i_green + + 112 * p_line->i_blue + 128) >> 8) + 128; + i_v = (int8_t)(( 112 * p_line->i_red - 94 * p_line->i_green - + 18 * p_line->i_blue + 128) >> 8) + 128; + + /* Build palette */ + fmt.p_palette->i_entries = 16; + for( i = 0; i < fmt.p_palette->i_entries; i++ ) + { + fmt.p_palette->palette[i][0] = i * 16 * i_y / 256; + fmt.p_palette->palette[i][1] = i_u; + fmt.p_palette->palette[i][2] = i_v; + fmt.p_palette->palette[i][3] = pi_gamma[i]; + fmt.p_palette->palette[i][3] = + (int)fmt.p_palette->palette[i][3] * (255 - p_line->i_alpha) / 255; + } + + p_dst = p_region->picture.Y_PIXELS; i_pitch = p_region->picture.Y_PITCH; /* Initialize the region pixels */ - memset( p_y, 0x00, i_pitch * p_region->fmt.i_height ); - memset( p_u, 0x80, i_pitch * p_region->fmt.i_height ); - memset( p_v, 0x80, i_pitch * p_region->fmt.i_height ); - memset( p_a, 0x00, i_pitch * p_region->fmt.i_height ); + memset( p_dst, 0, i_pitch * p_region->fmt.i_height ); -#define pi_gamma p_sys->pi_gamma - - for( p_line = p_string->p_lines; p_line != NULL; p_line = p_line->p_next ) + for( ; p_line != NULL; p_line = p_line->p_next ) { int i_glyph_tmax = 0; - int i_bitmap_offset, i_offset; + int i_bitmap_offset, i_offset, i_align_offset = 0; for( i = 0; p_line->pp_glyphs[i] != NULL; i++ ) { FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ]; i_glyph_tmax = __MAX( i_glyph_tmax, p_glyph->top ); } + if( p_line->i_width < i_width ) + { + if( p_region->i_text_align == SUBPICTURE_ALIGN_RIGHT ) + { + i_align_offset = i_width - p_line->i_width; + } + else if( p_region->i_text_align != SUBPICTURE_ALIGN_LEFT ) + { + i_align_offset = ( i_width - p_line->i_width ) / 2; + } + } + for( i = 0; p_line->pp_glyphs[i] != NULL; i++ ) { FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ]; i_offset = ( p_line->p_glyph_pos[ i ].y + - i_glyph_tmax - p_glyph->top + 1 ) * - i_pitch + p_line->p_glyph_pos[ i ].x + p_glyph->left + 1; + i_glyph_tmax - p_glyph->top + 2 ) * + i_pitch + p_line->p_glyph_pos[ i ].x + p_glyph->left + 2 + + i_align_offset; for( y = 0, i_bitmap_offset = 0; y < p_glyph->bitmap.rows; y++ ) { for( x = 0; x < p_glyph->bitmap.width; x++, i_bitmap_offset++ ) { - if( !pi_gamma[p_glyph->bitmap.buffer[i_bitmap_offset]] ) - continue; - - i_offset -= i_pitch; - p_a[i_offset + x] = ((uint16_t)p_a[i_offset + x] + - pi_gamma[p_glyph->bitmap.buffer[i_bitmap_offset]])*opacity/512; - i_offset += i_pitch; x--; - p_a[i_offset + x] = ((uint16_t)p_a[i_offset + x] + - pi_gamma[p_glyph->bitmap.buffer[i_bitmap_offset]])*opacity/512; - x += 2; - p_a[i_offset + x] = ((uint16_t)p_a[i_offset + x] + - pi_gamma[p_glyph->bitmap.buffer[i_bitmap_offset]])*opacity/512; - i_offset += i_pitch; x--; - p_a[i_offset + x] = ((uint16_t)p_a[i_offset + x] + - pi_gamma[p_glyph->bitmap.buffer[i_bitmap_offset]])*opacity/512; - i_offset -= i_pitch; + if( p_glyph->bitmap.buffer[i_bitmap_offset] ) + p_dst[i_offset+x] = + ((int)p_glyph->bitmap.buffer[i_bitmap_offset] + 8)/16; } i_offset += i_pitch; } + } + } - i_offset = ( p_line->p_glyph_pos[ i ].y + - i_glyph_tmax - p_glyph->top + 1 ) * - i_pitch + p_line->p_glyph_pos[ i ].x + p_glyph->left + 1; + /* Outlining (find something better than nearest neighbour filtering ?) */ + if( 1 ) + { + uint8_t *p_dst = p_region->picture.Y_PIXELS; + uint8_t *p_top = p_dst; /* Use 1st line as a cache */ + uint8_t left, current; - for( y = 0, i_bitmap_offset = 0; y < p_glyph->bitmap.rows; y++ ) + for( y = 1; y < (int)fmt.i_height - 1; y++ ) + { + memcpy( p_top, p_dst, fmt.i_width ); + p_dst += p_region->picture.Y_PITCH; + left = 0; + + for( x = 1; x < (int)fmt.i_width - 1; x++ ) { - for( x = 0; x < p_glyph->bitmap.width; x++, i_bitmap_offset++ ) - { - p_y[i_offset + x] = i_y*opacity*pi_gamma[p_glyph->bitmap.buffer[i_bitmap_offset]]/(256*256); - p_u[i_offset + x] = i_u; - p_v[i_offset + x] = i_v; - } - i_offset += i_pitch; + current = p_dst[x]; + p_dst[x] = ( 4 * (int)p_dst[x] + left + p_top[x] + p_dst[x+1] + + p_dst[x + p_region->picture.Y_PITCH]) / 8; + left = current; } - -#undef pi_gamma } + memset( p_top, 0, fmt.i_width ); } - return p_region; + + return VLC_SUCCESS; } /** - * This function receives a string and creates a subpicture for it. It - * also calculates the size needed for this string, and renders the + * This function renders a text subpicture region into another one. + * It also calculates the size needed for this string, and renders the * needed glyphs into memory. It is used as pf_add_string callback in * the vout method by this module */ -static subpicture_region_t *RenderText( filter_t *p_filter, - subpicture_t *p_subpic, - subpicture_region_t *p_region ) +static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, + subpicture_region_t *p_region_in ) { filter_sys_t *p_sys = p_filter->p_sys; - subpicture_data_t *p_string = 0; - line_desc_t *p_line = 0, *p_next = 0, *p_prev = 0; + line_desc_t *p_lines = 0, *p_line = 0, *p_next = 0, *p_prev = 0; int i, i_pen_y, i_pen_x, i_error, i_glyph_index, i_previous; uint32_t *psz_unicode, *psz_unicode_orig = 0, i_char, *psz_line_start; int i_string_length; char *psz_string; vlc_iconv_t iconv_handle = (vlc_iconv_t)(-1); - int i_font_color, i_font_opacity, i_font_size; - subpicture_region_t *p_res; + int i_font_color, i_font_alpha, i_font_size, i_red, i_green, i_blue; FT_BBox line; FT_BBox glyph_size; @@ -471,29 +453,25 @@ static subpicture_region_t *RenderText( filter_t *p_filter, FT_Glyph tmp_glyph; /* Sanity check */ - if( !p_region ) return NULL; - psz_string = p_region->psz_text; - if( !psz_string || !*psz_string ) goto error; - i_font_color = p_region->i_font_color; - i_font_opacity = p_region->i_font_opacity; - i_font_size = p_region->i_font_size; - - result.x = 0; - result.y = 0; - line.xMin = 0; - line.xMax = 0; - line.yMin = 0; - line.yMax = 0; - - /* Create and initialize private data for the subpicture */ - p_string = malloc( sizeof(subpicture_data_t) ); - if( !p_string ) - { - msg_Err( p_filter, "out of memory" ); - goto error; - } - p_string->p_lines = 0; - p_string->psz_text = strdup( psz_string ); + if( !p_region_in || !p_region_out ) return VLC_EGENERIC; + psz_string = p_region_in->psz_text; + if( !psz_string || !*psz_string ) return VLC_EGENERIC; + + i_font_color = __MAX( __MIN( p_region_in->i_text_color, 0xFFFFFF ), 0 ); + if( i_font_color == 0xFFFFFF ) i_font_color = p_sys->i_font_color; + + i_font_alpha = __MAX( __MIN( p_region_in->i_text_alpha, 255 ), 0 ); + if( !i_font_alpha ) i_font_alpha = 255 - p_sys->i_font_opacity; + + i_font_size = __MAX( __MIN( p_region_in->i_text_size, 255 ), 0 ); + SetFontSize( p_filter, i_font_size ); + + i_red = ( i_font_color & 0x00FF0000 ) >> 16; + i_green = ( i_font_color & 0x0000FF00 ) >> 8; + i_blue = i_font_color & 0x000000FF; + + result.x = result.y = 0; + line.xMin = line.xMax = line.yMin = line.yMax = 0; psz_unicode = psz_unicode_orig = malloc( ( strlen(psz_string) + 1 ) * sizeof(uint32_t) ); @@ -513,24 +491,6 @@ static subpicture_region_t *RenderText( filter_t *p_filter, goto error; } - /* Set up the glyphs for the desired font size. By definition, - p_sys->i_font_size is a valid value, else the initial Create would - have failed. Using -1 as a flag to use the freetype-fontsize */ - if ( i_font_size < 0 ) - { - FT_Set_Pixel_Sizes( p_sys->p_face, 0, p_sys->i_font_size ); - } - else - { - i_error = FT_Set_Pixel_Sizes( p_sys->p_face, 0, i_font_size ); - if( i_error ) - { - msg_Warn( p_filter, "Invalid font size to RenderText, using %d", - p_sys->i_font_size ); - FT_Set_Pixel_Sizes( p_sys->p_face, 0, p_sys->i_font_size ); - } - } - { char *p_in_buffer, *p_out_buffer; size_t i_in_bytes, i_out_bytes, i_out_bytes_left, i_ret; @@ -569,17 +529,14 @@ static subpicture_region_t *RenderText( filter_t *p_filter, /* Calculate relative glyph positions and a bounding box for the * entire string */ - p_line = NewLine( psz_string ); - if( p_line == NULL ) + if( !(p_line = NewLine( psz_string )) ) { msg_Err( p_filter, "out of memory" ); goto error; } - p_string->p_lines = p_line; - i_pen_x = 0; - i_pen_y = 0; - i_previous = 0; - i = 0; + p_lines = p_line; + i_pen_x = i_pen_y = 0; + i_previous = i = 0; psz_line_start = psz_unicode; #define face p_sys->p_face @@ -596,8 +553,7 @@ static subpicture_region_t *RenderText( filter_t *p_filter, if( i_char == '\n' ) { psz_line_start = psz_unicode; - p_next = NewLine( psz_string ); - if( p_next == NULL ) + if( !(p_next = NewLine( psz_string )) ) { msg_Err( p_filter, "out of memory" ); goto error; @@ -606,21 +562,21 @@ static subpicture_region_t *RenderText( filter_t *p_filter, p_line->i_width = line.xMax; p_line->i_height = face->size->metrics.height >> 6; p_line->pp_glyphs[ i ] = NULL; + p_line->i_alpha = i_font_alpha; + p_line->i_red = i_red; + p_line->i_green = i_green; + p_line->i_blue = i_blue; p_prev = p_line; p_line = p_next; result.x = __MAX( result.x, line.xMax ); result.y += face->size->metrics.height >> 6; i_pen_x = 0; - i_previous = 0; - line.xMin = 0; - line.xMax = 0; - line.yMin = 0; - line.yMax = 0; + i_previous = i = 0; + line.xMin = line.xMax = line.yMin = line.yMax = 0; i_pen_y += face->size->metrics.height >> 6; #if 0 msg_Dbg( p_filter, "Creating new line, i is %d", i ); #endif - i = 0; continue; } @@ -649,26 +605,21 @@ static subpicture_region_t *RenderText( filter_t *p_filter, goto error; } FT_Glyph_Get_CBox( tmp_glyph, ft_glyph_bbox_pixels, &glyph_size ); - i_error = FT_Glyph_To_Bitmap( &tmp_glyph, ft_render_mode_normal, - NULL, 1 ); + i_error = FT_Glyph_To_Bitmap( &tmp_glyph, ft_render_mode_normal, 0, 1); if( i_error ) continue; p_line->pp_glyphs[ i ] = (FT_BitmapGlyph)tmp_glyph; /* Do rest */ - line.xMax = p_line->p_glyph_pos[i].x + glyph_size.xMax - glyph_size.xMin + ((FT_BitmapGlyph)tmp_glyph)->left; - if( line.xMax > p_filter->fmt_out.video.i_visible_width - 20 ) + line.xMax = p_line->p_glyph_pos[i].x + glyph_size.xMax - + glyph_size.xMin + ((FT_BitmapGlyph)tmp_glyph)->left; + if( line.xMax > (int)p_filter->fmt_out.video.i_visible_width - 20 ) { p_line->pp_glyphs[ i ] = NULL; FreeLine( p_line ); p_line = NewLine( psz_string ); - if( p_prev ) - { - p_prev->p_next = p_line; - } - else - { - p_string->p_lines = p_line; - } + if( p_prev ) p_prev->p_next = p_line; + else p_lines = p_line; + while( psz_unicode > psz_line_start && *psz_unicode != ' ' ) { psz_unicode--; @@ -680,17 +631,12 @@ static subpicture_region_t *RenderText( filter_t *p_filter, } else { - *psz_unicode = '\n'; } psz_unicode = psz_line_start; i_pen_x = 0; - i_previous = 0; - line.xMin = 0; - line.xMax = 0; - line.yMin = 0; - line.yMax = 0; - i = 0; + i_previous = i = 0; + line.xMin = line.xMax = line.yMin = line.yMax = 0; continue; } line.yMax = __MAX( line.yMax, glyph_size.yMax ); @@ -704,46 +650,29 @@ static subpicture_region_t *RenderText( filter_t *p_filter, p_line->i_width = line.xMax; p_line->i_height = face->size->metrics.height >> 6; p_line->pp_glyphs[ i ] = NULL; + p_line->i_alpha = i_font_alpha; + p_line->i_red = i_red; + p_line->i_green = i_green; + p_line->i_blue = i_blue; result.x = __MAX( result.x, line.xMax ); result.y += line.yMax - line.yMin; - p_string->i_height = result.y; - p_string->i_width = result.x; #undef face #undef glyph -/* check to see whether to use the default color/opacity, or another one: */ - if( i_font_color < 0 ) - { - p_sys->i_blue = p_sys->i_font_color & 0x000000FF; - p_sys->i_green = ( p_sys->i_font_color & 0x0000FF00 ) >> 8; - p_sys->i_red = ( p_sys->i_font_color & 0x00FF0000 ) >> 16; - } - else - { - p_sys->i_blue = i_font_color & 0x000000FF; - p_sys->i_green = ( i_font_color & 0x0000FF00 ) >> 8; - p_sys->i_red = ( i_font_color & 0x00FF0000 ) >> 16; - } - if( i_font_opacity < 0 ) - { - p_sys->i_opacity = p_sys->i_font_opacity; - } - else - { - p_sys->i_opacity = (uint8_t)( i_font_opacity & 0x000000FF ); - } - p_res = Render( p_filter, p_subpic, p_string, p_sys->i_opacity, - p_sys->i_red, p_sys->i_green, p_sys->i_blue ); - FreeString( p_string ); + p_region_out->i_x = p_region_in->i_x; + p_region_out->i_y = p_region_in->i_y; + + Render( p_filter, p_region_out, p_lines, result.x, result.y ); + if( psz_unicode_orig ) free( psz_unicode_orig ); - return p_res; + FreeLines( p_lines ); + return VLC_SUCCESS; error: - FreeString( p_string ); - if( p_subpic ) p_filter->pf_sub_buffer_del( p_filter, p_subpic ); if( psz_unicode_orig ) free( psz_unicode_orig ); - return NULL; + FreeLines( p_lines ); + return VLC_EGENERIC; } static void FreeLine( line_desc_t *p_line ) @@ -758,30 +687,25 @@ static void FreeLine( line_desc_t *p_line ) free( p_line ); } -static void FreeString( subpicture_data_t *p_string ) +static void FreeLines( line_desc_t *p_lines ) { line_desc_t *p_line, *p_next; - if( !p_string ) return; + if( !p_lines ) return; - for( p_line = p_string->p_lines; p_line != NULL; p_line = p_next ) + for( p_line = p_lines; p_line != NULL; p_line = p_next ) { p_next = p_line->p_next; FreeLine( p_line ); } - - free( p_string->psz_text ); - free( p_string ); } static line_desc_t *NewLine( byte_t *psz_string ) { int i_count; line_desc_t *p_line = malloc( sizeof(line_desc_t) ); - if( !p_line ) - { - return NULL; - } + + if( !p_line ) return NULL; p_line->i_height = 0; p_line->i_width = 0; p_line->p_next = NULL; @@ -790,8 +714,7 @@ static line_desc_t *NewLine( byte_t *psz_string ) * sure the string is utf8. Better be safe than sorry. */ i_count = strlen( psz_string ); - p_line->pp_glyphs = malloc( sizeof(FT_BitmapGlyph) - * ( i_count + 1 ) ); + p_line->pp_glyphs = malloc( sizeof(FT_BitmapGlyph) * ( i_count + 1 ) ); if( p_line->pp_glyphs == NULL ) { free( p_line ); @@ -799,8 +722,7 @@ static line_desc_t *NewLine( byte_t *psz_string ) } p_line->pp_glyphs[0] = NULL; - p_line->p_glyph_pos = malloc( sizeof( FT_Vector ) - * i_count + 1 ); + p_line->p_glyph_pos = malloc( sizeof( FT_Vector ) * i_count + 1 ); if( p_line->p_glyph_pos == NULL ) { free( p_line->pp_glyphs ); @@ -810,3 +732,48 @@ static line_desc_t *NewLine( byte_t *psz_string ) return p_line; } + +static int SetFontSize( filter_t *p_filter, int i_size ) +{ + filter_sys_t *p_sys = p_filter->p_sys; + + if( i_size && i_size == p_sys->i_font_size ) return VLC_SUCCESS; + + if( !i_size ) + { + vlc_value_t val; + + if( !p_sys->i_default_font_size && + p_sys->i_display_height == (int)p_filter->fmt_out.video.i_height ) + return VLC_SUCCESS; + + if( p_sys->i_default_font_size ) + { + i_size = p_sys->i_default_font_size; + } + else + { + var_Get( p_filter, "freetype-rel-fontsize", &val ); + i_size = (int)p_filter->fmt_out.video.i_height / val.i_int; + p_filter->p_sys->i_display_height = + p_filter->fmt_out.video.i_height; + } + if( i_size <= 0 ) + { + msg_Warn( p_filter, "Invalid fontsize, using 12" ); + i_size = 12; + } + + msg_Dbg( p_filter, "Using fontsize: %i", i_size ); + } + + p_sys->i_font_size = i_size; + + if( FT_Set_Pixel_Sizes( p_sys->p_face, 0, i_size ) ) + { + msg_Err( p_filter, "couldn't set font size to %d", i_size ); + return VLC_EGENERIC; + } + + return VLC_SUCCESS; +}