📄 freetype.c
字号:
/***************************************************************************** * freetype.c : Put text on the video, using freetype2 ***************************************************************************** * Copyright (C) 2002 - 2005 the VideoLAN team * $Id: freetype.c 16987 2006-10-08 12:54:12Z jpsaman $ * * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org> * Gildas Bazin <gbazin@videolan.org> * * 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 * (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. * * You should have received a copy of the GNU 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. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#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 "vlc_osd.h"#include "vlc_block.h"#include "vlc_filter.h"#include <math.h>#ifdef HAVE_ERRNO_H# include <errno.h>#endif#include <ft2build.h>#include FT_FREETYPE_H#include FT_GLYPH_H#ifdef __APPLE__#define DEFAULT_FONT "/System/Library/Fonts/LucidaGrande.dfont"#elif defined( SYS_BEOS )#define DEFAULT_FONT "/boot/beos/etc/fonts/ttfonts/Swiss721.ttf"#elif defined( WIN32 )#define DEFAULT_FONT "" /* Default font found at run-time */#else#define DEFAULT_FONT "/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf"#endif#if defined(HAVE_FRIBIDI)#include <fribidi/fribidi.h>#endiftypedef struct line_desc_t line_desc_t;/***************************************************************************** * Local prototypes *****************************************************************************/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 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 *****************************************************************************/#define FONT_TEXT N_("Font")#define FONT_LONGTEXT N_("Filename for the font you want to use")#define FONTSIZE_TEXT N_("Font size in pixels")#define FONTSIZE_LONGTEXT N_("This is the default size of the fonts " \ "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_LONGTEXT N_("The opacity (inverse of transparency) of the " \ "text that will be rendered on the video. 0 = transparent, " \ "255 = totally opaque. " )#define COLOR_TEXT N_("Text default color")#define COLOR_LONGTEXT N_("The color of the text that will be rendered on "\ "the video. This must be an hexadecimal (like HTML colors). The first two "\ "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\ " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )#define FONTSIZER_TEXT N_("Relative font size")#define FONTSIZER_LONGTEXT N_("This is the relative default size of the " \ "fonts that will be rendered on the video. If absolute font size is set, "\ "relative size will be overriden." )static int pi_sizes[] = { 20, 18, 16, 12, 6 };static char *ppsz_sizes_text[] = { N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") };#define YUVP_TEXT N_("Use YUVP renderer")#define YUVP_LONGTEXT N_("This renders the font using \"paletized YUV\". " \ "This option is only needed if you want to encode into DVB subtitles" )#define EFFECT_TEXT N_("Font Effect")#define EFFECT_LONGTEXT N_("It is possible to apply effects to the rendered " \"text to improve its readability." )#define EFFECT_BACKGROUND 1 #define EFFECT_OUTLINE 2#define EFFECT_OUTLINE_FAT 3static int pi_effects[] = { 1, 2, 3 };static char *ppsz_effects_text[] = { N_("Background"),N_("Outline"), N_("Fat Outline") };static int pi_color_values[] = { 0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080, 0x00000080, 0x000000FF, 0x0000FFFF }; static char *ppsz_color_descriptions[] = { N_("Black"), N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"), N_("Teal"), N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"), N_("Aqua") };vlc_module_begin(); set_shortname( _("Text renderer")); set_description( _("Freetype2 font renderer") ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_SUBPIC ); 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 ); /* 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_TRUE ); /* hook to the color values list, with default 0x00ffffff = white */ add_integer( "freetype-color", 0x00FFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT, VLC_FALSE ); change_integer_list( pi_color_values, ppsz_color_descriptions, 0 ); add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT, FONTSIZER_LONGTEXT, VLC_FALSE ); change_integer_list( pi_sizes, ppsz_sizes_text, 0 ); add_integer( "freetype-effect", 2, NULL, EFFECT_TEXT, EFFECT_LONGTEXT, VLC_FALSE ); change_integer_list( pi_effects, ppsz_effects_text, 0 ); add_bool( "freetype-yuvp", 0, NULL, YUVP_TEXT, YUVP_LONGTEXT, VLC_TRUE ); set_capability( "text renderer", 100 ); add_shortcut( "text" ); set_callbacks( Create, Destroy );vlc_module_end();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 int Render( filter_t *, subpicture_region_t *, line_desc_t *, int, int);static void FreeLines( line_desc_t * );static void FreeLine( line_desc_t * );/***************************************************************************** * filter_sys_t: freetype local data ***************************************************************************** * This structure is part of the video output thread descriptor. * It describes the freetype specific properties of an output thread. *****************************************************************************/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; int i_font_color; int i_font_size; int i_effect; int i_default_font_size; int i_display_height;};/***************************************************************************** * Create: allocates osd-text video thread output method ***************************************************************************** * This function allocates and initializes a Clone vout method. *****************************************************************************/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_error; vlc_value_t val; /* Allocate structure */ p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) { msg_Err( p_filter, "out of memory" ); return VLC_ENOMEM; } 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-font", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-fontsize", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-rel-fontsize", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-effect", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_filter, "freetype-opacity", &val ); p_sys->i_font_opacity = __MAX( __MIN( val.i_int, 255 ), 0 ); var_Create( p_filter, "freetype-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_filter, "freetype-color", &val ); p_sys->i_font_color = __MAX( __MIN( val.i_int, 0xFFFFFF ), 0 ); p_sys->i_effect = var_GetInteger( p_filter, "freetype-effect" ); /* Look what method was requested */ var_Get( p_filter, "freetype-font", &val ); psz_fontfile = val.psz_string; if( !psz_fontfile || !*psz_fontfile ) { if( psz_fontfile ) free( psz_fontfile ); psz_fontfile = (char *)malloc( PATH_MAX + 1 );#ifdef WIN32 GetWindowsDirectory( psz_fontfile, PATH_MAX + 1 ); strcat( psz_fontfile, "\\fonts\\arial.ttf" );#elif __APPLE__ strcpy( psz_fontfile, DEFAULT_FONT );#else msg_Err( p_filter, "user didn't specify a font" ); goto error;#endif } i_error = FT_Init_FreeType( &p_sys->p_library ); if( i_error ) { msg_Err( p_filter, "couldn't initialize freetype" ); goto error; } i_error = FT_New_Face( p_sys->p_library, psz_fontfile ? psz_fontfile : "", 0, &p_sys->p_face ); if( i_error == FT_Err_Unknown_File_Format ) { msg_Err( p_filter, "file %s have unknown format", psz_fontfile ); goto error; } else if( i_error ) { msg_Err( p_filter, "failed to load font file %s", psz_fontfile ); goto error; } i_error = FT_Select_Charmap( p_sys->p_face, ft_encoding_unicode ); if( i_error ) { msg_Err( p_filter, "font has no unicode translation table" ); goto error; } p_sys->i_use_kerning = FT_HAS_KERNING( p_sys->p_face ); var_Get( p_filter, "freetype-fontsize", &val ); 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_text = RenderText; return VLC_SUCCESS; error: if( p_sys->p_face ) FT_Done_Face( p_sys->p_face ); if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library ); if( psz_fontfile ) free( psz_fontfile ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * Destroy: destroy Clone video thread output method ***************************************************************************** * Clean up all data and library connections *****************************************************************************/static void Destroy( vlc_object_t *p_this ){ filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys = p_filter->p_sys; FT_Done_Face( p_sys->p_face ); FT_Done_FreeType( p_sys->p_library ); free( p_sys );}/***************************************************************************** * Render: place string in picture ***************************************************************************** * This function merges the previously rendered freetype glyphs into a picture *****************************************************************************/static int Render( filter_t *p_filter, subpicture_region_t *p_region, line_desc_t *p_line, int i_width, int i_height ){ static uint8_t pi_gamma[16] = {0x00, 0x52, 0x84, 0x96, 0xb8, 0xca, 0xdc, 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; uint8_t *p_dst; video_format_t fmt; int i, x, y, i_pitch; 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','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_tmp = spu_CreateRegion( p_filter, &fmt ); if( !p_region_tmp ) { msg_Err( p_filter, "cannot allocate SPU region" ); return VLC_EGENERIC; } p_region->fmt = p_region_tmp->fmt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -