?? quartztext.c
字號:
/***************************************************************************** * quartztext.c : Put text on the video, using Mac OS X Quartz Engine ***************************************************************************** * Copyright (C) 2007 the VideoLAN team * $Id: e307ce779d3b4126eee70cd4959a7e6b1d44c67c $ * * Authors: Bernie Purcell <bitmap@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//////////////////////////////////////////////////////////////////////////////#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_vout.h>#include <vlc_osd.h>#include <vlc_block.h>#include <vlc_filter.h>#include <vlc_stream.h>#include <vlc_xml.h>#include <vlc_input.h>#include <math.h>#include <Carbon/Carbon.h>#define DEFAULT_FONT "Verdana"#define DEFAULT_FONT_COLOR 0xffffff#define DEFAULT_REL_FONT_SIZE 16#define VERTICAL_MARGIN 3#define HORIZONTAL_MARGIN 10//////////////////////////////////////////////////////////////////////////////// Local prototypes//////////////////////////////////////////////////////////////////////////////static int Create ( vlc_object_t * );static void Destroy( vlc_object_t * );static int LoadFontsFromAttachments( filter_t *p_filter );static int RenderText( filter_t *, subpicture_region_t *, subpicture_region_t * );static int RenderHtml( filter_t *, subpicture_region_t *, subpicture_region_t * );static int GetFontSize( filter_t *p_filter );static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, UniChar *psz_utfString, uint32_t i_text_len, uint32_t i_runs, uint32_t *pi_run_lengths, ATSUStyle *pp_styles );static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, uint32_t i_font_color, bool b_bold, bool b_italic, bool b_uline );//////////////////////////////////////////////////////////////////////////////// Module descriptor//////////////////////////////////////////////////////////////////////////////// The preferred way to set font style information is for it to come from the// subtitle file, and for it to be rendered with RenderHtml instead of// RenderText. This module, unlike Freetype, doesn't provide any options to// override the fallback font selection used when this style information is// absent.#define FONT_TEXT N_("Font")#define FONT_LONGTEXT N_("Name for the font you want to use")#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." )#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" )static const int pi_color_values[] = { 0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000, 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00808000, 0x00008000, 0x00008080, 0x0000FF00, 0x00800080, 0x00000080, 0x000000FF, 0x0000FFFF };static const char *const 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") };static const int pi_sizes[] = { 20, 18, 16, 12, 6 };static const char *const ppsz_sizes_text[] = { N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") };vlc_module_begin(); set_shortname( N_("Mac Text renderer")); set_description( N_("Quartz font renderer") ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_SUBPIC ); add_string( "quartztext-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, false ); add_integer( "quartztext-rel-fontsize", DEFAULT_REL_FONT_SIZE, NULL, FONTSIZER_TEXT, FONTSIZER_LONGTEXT, false ); change_integer_list( pi_sizes, ppsz_sizes_text, NULL ); add_integer( "quartztext-color", 0x00FFFFFF, NULL, COLOR_TEXT, COLOR_LONGTEXT, false ); change_integer_list( pi_color_values, ppsz_color_descriptions, NULL ); set_capability( "text renderer", 120 ); add_shortcut( "text" ); set_callbacks( Create, Destroy );vlc_module_end();typedef struct font_stack_t font_stack_t;struct font_stack_t{ char *psz_name; int i_size; uint32_t i_color; // ARGB font_stack_t *p_next;};typedef struct offscreen_bitmap_t offscreen_bitmap_t;struct offscreen_bitmap_t{ uint8_t *p_data; int i_bitsPerChannel; int i_bitsPerPixel; int i_bytesPerPixel; int i_bytesPerRow;};//////////////////////////////////////////////////////////////////////////////// filter_sys_t: quartztext 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{ char *psz_font_name; uint8_t i_font_opacity; int i_font_color; int i_font_size; ATSFontContainerRef *p_fonts; int i_fonts;};//////////////////////////////////////////////////////////////////////////////// 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; // Allocate structure p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_sys->psz_font_name = var_CreateGetString( p_this, "quartztext-font" ); p_sys->i_font_opacity = 255; p_sys->i_font_color = __MAX( __MIN( var_CreateGetInteger( p_this, "quartztext-color" ) , 0xFFFFFF ), 0 ); p_sys->i_font_size = GetFontSize( p_filter ); p_filter->pf_render_text = RenderText; p_filter->pf_render_html = RenderHtml; p_sys->p_fonts = NULL; p_sys->i_fonts = 0; LoadFontsFromAttachments( p_filter ); return VLC_SUCCESS;}//////////////////////////////////////////////////////////////////////////////// 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; if( p_sys->p_fonts ) { int k; for( k = 0; k < p_sys->i_fonts; k++ ) { ATSFontDeactivate( p_sys->p_fonts[k], NULL, kATSOptionFlagsDefault ); } free( p_sys->p_fonts ); } free( p_sys->psz_font_name ); free( p_sys );}//////////////////////////////////////////////////////////////////////////////// Make any TTF/OTF fonts present in the attachments of the media file// available to the Quartz engine for text rendering//////////////////////////////////////////////////////////////////////////////static int LoadFontsFromAttachments( filter_t *p_filter ){ filter_sys_t *p_sys = p_filter->p_sys; input_thread_t *p_input; input_attachment_t **pp_attachments; int i_attachments_cnt; int k; int rv = VLC_SUCCESS; p_input = (input_thread_t *)vlc_object_find( p_filter, VLC_OBJECT_INPUT, FIND_PARENT ); if( ! p_input ) return VLC_EGENERIC; if( VLC_SUCCESS != input_Control( p_input, INPUT_GET_ATTACHMENTS, &pp_attachments, &i_attachments_cnt )) { vlc_object_release(p_input); return VLC_EGENERIC; } p_sys->i_fonts = 0; p_sys->p_fonts = malloc( i_attachments_cnt * sizeof( ATSFontContainerRef ) ); if(! p_sys->p_fonts ) rv = VLC_ENOMEM; for( k = 0; k < i_attachments_cnt; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; if( p_sys->p_fonts ) { if(( !strcmp( p_attach->psz_mime, "application/x-truetype-font" ) || // TTF !strcmp( p_attach->psz_mime, "application/x-font-otf" ) ) && // OTF ( p_attach->i_data > 0 ) && ( p_attach->p_data != NULL ) ) { ATSFontContainerRef container; if( noErr == ATSFontActivateFromMemory( p_attach->p_data, p_attach->i_data, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &container )) { p_sys->p_fonts[ p_sys->i_fonts++ ] = container; } } } vlc_input_attachment_Delete( p_attach ); } free( pp_attachments ); vlc_object_release(p_input); return rv;}#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4// Original version of these functions available on:// http://developer.apple.com/documentation/Carbon/Conceptual/QuickDrawToQuartz2D/tq_color/chapter_4_section_3.html#define kGenericRGBProfilePathStr "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"static CMProfileRef OpenGenericProfile( void ){ static CMProfileRef cached_rgb_prof = NULL; // Create the profile reference only once if( cached_rgb_prof == NULL ) { OSStatus err; CMProfileLocation loc; loc.locType = cmPathBasedProfile; strcpy( loc.u.pathLoc.path, kGenericRGBProfilePathStr ); err = CMOpenProfile( &cached_rgb_prof, &loc ); if( err != noErr ) { cached_rgb_prof = NULL; } } if( cached_rgb_prof ) { // Clone the profile reference so that the caller has // their own reference, not our cached one. CMCloneProfileRef( cached_rgb_prof ); } return cached_rgb_prof;}static CGColorSpaceRef CreateGenericRGBColorSpace( void ){ static CGColorSpaceRef p_generic_rgb_cs = NULL; if( p_generic_rgb_cs == NULL ) { CMProfileRef generic_rgb_prof = OpenGenericProfile(); if( generic_rgb_prof ) { p_generic_rgb_cs = CGColorSpaceCreateWithPlatformColorSpace( generic_rgb_prof ); CMCloseProfile( generic_rgb_prof ); } } return p_generic_rgb_cs;}#endifstatic char *EliminateCRLF( char *psz_string ){ char *p; char *q; for( p = psz_string; p && *p; p++ ) { if( ( *p == '\r' ) && ( *(p+1) == '\n' ) ) { for( q = p + 1; *q; q++ ) *( q - 1 ) = *q; *( q - 1 ) = '\0'; } } return psz_string;}// Convert UTF-8 string to UTF-16 character array -- internal Mac Endian-ness ;// we don't need to worry about bidirectional text conversion as ATSUI should// handle that for us automaticallystatic void ConvertToUTF16( const char *psz_utf8_str, uint32_t *pi_strlen, UniChar **ppsz_utf16_str ){ CFStringRef p_cfString; int i_string_length; p_cfString = CFStringCreateWithCString( NULL, psz_utf8_str, kCFStringEncodingUTF8 ); if( !p_cfString ) return; i_string_length = CFStringGetLength( p_cfString ); if( pi_strlen ) *pi_strlen = i_string_length; if( !*ppsz_utf16_str ) *ppsz_utf16_str = (UniChar *) calloc( i_string_length, sizeof( UniChar ) ); CFStringGetCharacters( p_cfString, CFRangeMake( 0, i_string_length ), *ppsz_utf16_str ); CFRelease( p_cfString );}// Renders a text subpicture region into another one.// It is used as pf_add_string callback in the vout method by this modulestatic 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; UniChar *psz_utf16_str = NULL; uint32_t i_string_length; char *psz_string; int i_font_color, i_font_alpha, i_font_size; vlc_value_t val; int i_scale = 1000; p_sys->i_font_size = GetFontSize( p_filter );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -