📄 freetype.c
字号:
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; free( psz_fontfile ); p_sys->pp_font_attachments = NULL; p_sys->i_font_attachments = 0; p_filter->pf_render_text = RenderText;#ifdef HAVE_FONTCONFIG p_filter->pf_render_html = RenderHtml;#else p_filter->pf_render_html = NULL;#endif LoadFontsFromAttachments( p_filter ); 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 ); 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; if( p_sys->pp_font_attachments ) { int k; for( k = 0; k < p_sys->i_font_attachments; k++ ) vlc_input_attachment_Delete( p_sys->pp_font_attachments[k] ); free( p_sys->pp_font_attachments ); }#ifdef HAVE_FONTCONFIG FontBuilderDetach( p_filter, p_sys->p_fontbuilder );#endif /* FcFini asserts calling the subfunction FcCacheFini() * even if no other library functions have been made since FcInit(), * so don't call it. */ FT_Done_Face( p_sys->p_face ); FT_Done_FreeType( p_sys->p_library ); free( p_sys );}#ifdef HAVE_FONTCONFIGstatic vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock ){ /* Check for an existing Fontbuilder thread */ vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); vlc_object_t *p_fontbuilder = vlc_object_find_name( p_filter->p_libvlc, "fontlist builder", FIND_CHILD ); if( !p_fontbuilder ) { /* Create the FontBuilderThread thread as a child of a top-level * object, so that it can survive the destruction of the * freetype object - the fontlist only needs to be built once, * and calling the fontbuild a second time while the first is * still in progress can cause thread instabilities. * * XXX The fontbuilder will be destroy as soon as it is unused. */ p_fontbuilder = vlc_object_create( p_filter->p_libvlc, sizeof(vlc_object_t) ); if( p_fontbuilder ) { p_fontbuilder->psz_object_name = strdup( "fontlist builder" ); p_fontbuilder->p_private = NULL; vlc_object_set_destructor( p_fontbuilder, FontBuilderDestructor ); vlc_object_attach( p_fontbuilder, p_filter->p_libvlc ); var_Create( p_fontbuilder, "build-done", VLC_VAR_BOOL ); var_SetBool( p_fontbuilder, "build-done", false ); if( vlc_thread_create( p_fontbuilder, "fontlist builder", FontBuilderThread, VLC_THREAD_PRIORITY_LOW, false ) ) { msg_Warn( p_filter, "fontconfig database builder thread can't " "be launched. Font styling support will be limited." ); } } } if( p_fontbuilder ) { var_AddCallback( p_fontbuilder, "build-done", FontBuilderDone, p_filter ); FontBuilderGetFcConfig( p_filter, p_fontbuilder ); } vlc_mutex_unlock( p_lock ); *pp_lock = p_lock; return p_fontbuilder;}static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ){ vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); if( p_fontbuilder ) { const bool b_alive = vlc_object_alive( p_fontbuilder ); var_DelCallback( p_fontbuilder, "build-done", FontBuilderDone, p_filter ); /* We wait for the thread on the first FontBuilderDetach */ if( b_alive ) { vlc_object_kill( p_fontbuilder ); vlc_mutex_unlock( lock ); /* We need to unlock otherwise we may not join (the thread waiting * for the lock). It is safe to unlock as no one else will try a * join and we have a reference on the object) */ vlc_thread_join( p_fontbuilder ); vlc_mutex_lock( lock ); } vlc_object_release( p_fontbuilder ); } vlc_mutex_unlock( lock );}static void* FontBuilderThread( vlc_object_t *p_this ){ FcConfig *p_fontconfig = FcInitLoadConfig(); vlc_thread_ready( p_this ); if( p_fontconfig ) { mtime_t t1, t2; //msg_Dbg( p_this, "Building font database..." ); msg_Dbg( p_this, "Building font database..." ); t1 = mdate(); if(! FcConfigBuildFonts( p_fontconfig )) { /* Don't destroy the fontconfig object - we won't be able to do * italics or bold or change the font face, but we will still * be able to do underline and change the font size. */ msg_Err( p_this, "fontconfig database can't be built. " "Font styling won't be available" ); } t2 = mdate(); msg_Dbg( p_this, "Finished building font database." ); msg_Dbg( p_this, "Took %ld seconds", (long)((t2 - t1)/1000000) ); vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); p_this->p_private = p_fontconfig; vlc_mutex_unlock( p_lock ); var_SetBool( p_this, "build-done", true ); } return NULL;}static void FontBuilderGetFcConfig( filter_t *p_filter, vlc_object_t *p_fontbuilder ){ filter_sys_t *p_sys = p_filter->p_sys; p_sys->p_fontconfig = p_fontbuilder->p_private; p_sys->b_fontconfig_ok = p_fontbuilder->p_private != NULL;}static void FontBuilderDestructor( vlc_object_t *p_this ){ FcConfig *p_fontconfig = p_this->p_private; if( p_fontconfig ) FcConfigDestroy( p_fontconfig );}static int FontBuilderDone( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *param ){ filter_t *p_filter = param; if( newval.b_bool ) { vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); FontBuilderGetFcConfig( p_filter, p_this ); vlc_mutex_unlock( p_lock ); } VLC_UNUSED(psz_var); VLC_UNUSED(oldval); return VLC_SUCCESS;}#endif/***************************************************************************** * Make any TTF/OTF fonts present in the attachments of the media file * and store them for later use by the FreeType Engine *****************************************************************************/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_font_attachments = 0; p_sys->pp_font_attachments = malloc( i_attachments_cnt * sizeof( input_attachment_t * )); if(! p_sys->pp_font_attachments ) rv = VLC_ENOMEM; for( k = 0; k < i_attachments_cnt; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; if( p_sys->pp_font_attachments ) { 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 ) ) { p_sys->pp_font_attachments[ p_sys->i_font_attachments++ ] = p_attach; } else { vlc_input_attachment_Delete( p_attach ); } } else { vlc_input_attachment_Delete( p_attach ); } } free( pp_attachments ); vlc_object_release(p_input); return rv;}/***************************************************************************** * 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 const 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; if( p_region->fmt.i_visible_width > 0 ) fmt.i_visible_width = p_region->fmt.i_visible_width; if( p_region->fmt.i_visible_height > 0 ) fmt.i_visible_height = p_region->fmt.i_visible_height; 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; 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 < 8; i++ ) { fmt.p_palette->palette[i][0] = 0; fmt.p_palette->palette[i][1] = 0x80; fmt.p_palette->palette[i][2] = 0x80; 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; } for( i = 8; 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_dst, 0, i_pitch * p_region->fmt.i_height ); for( ; p_line != NULL; p_line = p_line->p_next ) { int i_glyph_tmax = 0; 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_align & 0x3) == SUBPICTURE_ALIGN_RIGHT ) { i_align_offset = i_width - p_line->i_width; } else if( (p_region->i_align & 0x3) != 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 + 2 ) * i_pitch + p_line->p_glyph_pos[ i ].x + p_glyph->left + 2 + i_align_offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -