⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freetype.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 2 页
字号:
            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( 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;            }        }    }    /* 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 = 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++ )            {                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;            }        }        memset( p_top, 0, fmt.i_width );    }    return VLC_SUCCESS;}/** * 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 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;    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_alpha, i_font_size, i_red, i_green, i_blue;    FT_BBox line;    FT_BBox glyph_size;    FT_Vector result;    FT_Glyph tmp_glyph;    /* Sanity check */    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) );    if( psz_unicode == NULL )    {        msg_Err( p_filter, "out of memory" );        goto error;    }#if defined(WORDS_BIGENDIAN)    iconv_handle = vlc_iconv_open( "UCS-4BE", "UTF-8" );#else    iconv_handle = vlc_iconv_open( "UCS-4LE", "UTF-8" );#endif    if( iconv_handle == (vlc_iconv_t)-1 )    {        msg_Warn( p_filter, "unable to do conversion" );        goto error;    }    {        char *p_in_buffer, *p_out_buffer;        size_t i_in_bytes, i_out_bytes, i_out_bytes_left, i_ret;        i_in_bytes = strlen( psz_string );        i_out_bytes = i_in_bytes * sizeof( uint32_t );        i_out_bytes_left = i_out_bytes;        p_in_buffer = psz_string;        p_out_buffer = (char *)psz_unicode;        i_ret = vlc_iconv( iconv_handle, &p_in_buffer, &i_in_bytes,                           &p_out_buffer, &i_out_bytes_left );        vlc_iconv_close( iconv_handle );        if( i_in_bytes )        {            msg_Warn( p_filter, "failed to convert string to unicode (%s), "                      "bytes left %d", strerror(errno), i_in_bytes );            goto error;        }        *(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;        FriBidiCharType base_dir = FRIBIDI_TYPE_ON;        p_fribidi_string = malloc( (i_string_length + 1) * sizeof(uint32_t) );        fribidi_log2vis( (FriBidiChar*)psz_unicode, i_string_length,                         &base_dir, (FriBidiChar*)p_fribidi_string, 0, 0, 0 );        free( psz_unicode_orig );        psz_unicode = psz_unicode_orig = p_fribidi_string;        p_fribidi_string[ i_string_length ] = 0;    }#endif    /* Calculate relative glyph positions and a bounding box for the     * entire string */    if( !(p_line = NewLine( psz_string )) )    {        msg_Err( p_filter, "out of memory" );        goto error;    }    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#define glyph face->glyph    while( *psz_unicode )    {        i_char = *psz_unicode++;        if( i_char == '\r' ) /* ignore CR chars wherever they may be */        {            continue;        }        if( i_char == '\n' )        {            psz_line_start = psz_unicode;            if( !(p_next = NewLine( psz_string )) )            {                msg_Err( p_filter, "out of memory" );                goto error;            }            p_line->p_next = p_next;            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 = 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            continue;        }        i_glyph_index = FT_Get_Char_Index( face, i_char );        if( p_sys->i_use_kerning && i_glyph_index            && i_previous )        {            FT_Vector delta;            FT_Get_Kerning( face, i_previous, i_glyph_index,                            ft_kerning_default, &delta );            i_pen_x += delta.x >> 6;        }        p_line->p_glyph_pos[ i ].x = i_pen_x;        p_line->p_glyph_pos[ i ].y = i_pen_y;        i_error = FT_Load_Glyph( face, i_glyph_index, FT_LOAD_DEFAULT );        if( i_error )        {            msg_Err( p_filter, "FT_Load_Glyph returned %d", i_error );            goto error;        }        i_error = FT_Get_Glyph( glyph, &tmp_glyph );        if( i_error )        {            msg_Err( p_filter, "FT_Get_Glyph returned %d", i_error );            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, 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 > (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_lines = p_line;            while( psz_unicode > psz_line_start && *psz_unicode != ' ' )            {                psz_unicode--;            }            if( psz_unicode == psz_line_start )            {                msg_Warn( p_filter, "unbreakable string" );                goto error;            }            else            {                *psz_unicode = '\n';            }            psz_unicode = psz_line_start;            i_pen_x = 0;            i_previous = i = 0;            line.xMin = line.xMax = line.yMin = line.yMax = 0;            continue;        }        line.yMax = __MAX( line.yMax, glyph_size.yMax );        line.yMin = __MIN( line.yMin, glyph_size.yMin );        i_previous = i_glyph_index;        i_pen_x += glyph->advance.x >> 6;        i++;    }    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;#undef face#undef glyph    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 );    FreeLines( p_lines );    return VLC_SUCCESS; error:    if( psz_unicode_orig ) free( psz_unicode_orig );    FreeLines( p_lines );    return VLC_EGENERIC;}static void FreeLine( line_desc_t *p_line ){    unsigned int i;    for( i = 0; p_line->pp_glyphs[ i ] != NULL; i++ )    {        FT_Done_Glyph( (FT_Glyph)p_line->pp_glyphs[ i ] );    }    free( p_line->pp_glyphs );    free( p_line->p_glyph_pos );    free( p_line );}static void FreeLines( line_desc_t *p_lines ){    line_desc_t *p_line, *p_next;    if( !p_lines ) return;    for( p_line = p_lines; p_line != NULL; p_line = p_next )    {        p_next = p_line->p_next;        FreeLine( p_line );    }}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;    p_line->i_height = 0;    p_line->i_width = 0;    p_line->p_next = NULL;    /* We don't use CountUtf8Characters() here because we are not acutally     * 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 ) );    if( p_line->pp_glyphs == NULL )    {        free( p_line );        return NULL;    }    p_line->pp_glyphs[0] = NULL;    p_line->p_glyph_pos = malloc( sizeof( FT_Vector ) * i_count + 1 );    if( p_line->p_glyph_pos == NULL )    {        free( p_line->pp_glyphs );        free( p_line );        return NULL;    }    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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -