quartztext.c

来自「VLC Player Source Code」· C语言 代码 · 共 1,191 行 · 第 1/3 页

C
1,191
字号
    // 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;    if( VLC_SUCCESS == var_Get( p_filter, "scale", &val ))        i_scale = val.i_int;    if( p_region_in->p_style )    {        i_font_color = __MAX( __MIN( p_region_in->p_style->i_font_color, 0xFFFFFF ), 0 );        i_font_alpha = __MAX( __MIN( p_region_in->p_style->i_font_alpha, 255 ), 0 );        i_font_size  = __MAX( __MIN( p_region_in->p_style->i_font_size, 255 ), 0 ) * i_scale / 1000;    }    else    {        i_font_color = p_sys->i_font_color;        i_font_alpha = 255 - p_sys->i_font_opacity;        i_font_size  = p_sys->i_font_size;    }    if( !i_font_alpha ) i_font_alpha = 255 - p_sys->i_font_opacity;    ConvertToUTF16( EliminateCRLF( psz_string ), &i_string_length, &psz_utf16_str );    p_region_out->i_x = p_region_in->i_x;    p_region_out->i_y = p_region_in->i_y;    if( psz_utf16_str != NULL )    {        ATSUStyle p_style = CreateStyle( p_sys->psz_font_name, i_font_size,                                         (i_font_color & 0xffffff) |                                         ((i_font_alpha & 0xff) << 24),                                         false, false, false );        if( p_style )        {            RenderYUVA( p_filter, p_region_out, psz_utf16_str, i_string_length,                        1, &i_string_length, &p_style );        }        ATSUDisposeStyle( p_style );        free( psz_utf16_str );    }    return VLC_SUCCESS;}static ATSUStyle CreateStyle( char *psz_fontname, int i_font_size, uint32_t i_font_color,                              bool b_bold, bool b_italic, bool b_uline ){    ATSUStyle   p_style;    OSStatus    status;    uint32_t    i_tag_cnt;    float f_red   = (float)(( i_font_color & 0x00FF0000 ) >> 16) / 255.0;    float f_green = (float)(( i_font_color & 0x0000FF00 ) >>  8) / 255.0;    float f_blue  = (float)(  i_font_color & 0x000000FF        ) / 255.0;    float f_alpha = ( 255.0 - (float)(( i_font_color & 0xFF000000 ) >> 24)) / 255.0;    ATSUFontID           font;    Fixed                font_size  = IntToFixed( i_font_size );    ATSURGBAlphaColor    font_color = { f_red, f_green, f_blue, f_alpha };    Boolean              bold       = b_bold;    Boolean              italic     = b_italic;    Boolean              uline      = b_uline;    ATSUAttributeTag tags[]        = { kATSUSizeTag, kATSURGBAlphaColorTag, kATSUQDItalicTag,                                       kATSUQDBoldfaceTag, kATSUQDUnderlineTag, kATSUFontTag };    ByteCount sizes[]              = { sizeof( Fixed ), sizeof( ATSURGBAlphaColor ), sizeof( Boolean ),                                       sizeof( Boolean ), sizeof( Boolean ), sizeof( ATSUFontID )};    ATSUAttributeValuePtr values[] = { &font_size, &font_color, &italic, &bold, &uline, &font };    i_tag_cnt = sizeof( tags ) / sizeof( ATSUAttributeTag );    status = ATSUFindFontFromName( psz_fontname,                                   strlen( psz_fontname ),                                   kFontFullName,                                   kFontNoPlatform,                                   kFontNoScript,                                   kFontNoLanguageCode,                                   &font );    if( status != noErr )    {        // If we can't find a suitable font, just do everything else        i_tag_cnt--;    }    if( noErr == ATSUCreateStyle( &p_style ) )    {        if( noErr == ATSUSetAttributes( p_style, i_tag_cnt, tags, sizes, values ) )        {            return p_style;        }        ATSUDisposeStyle( p_style );    }    return NULL;}static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size,                     uint32_t i_color ){    font_stack_t *p_new;    if( !p_font )        return VLC_EGENERIC;    p_new = malloc( sizeof( font_stack_t ) );    if( ! p_new )        return VLC_ENOMEM;    p_new->p_next = NULL;    if( psz_name )        p_new->psz_name = strdup( psz_name );    else        p_new->psz_name = NULL;    p_new->i_size   = i_size;    p_new->i_color  = i_color;    if( !*p_font )    {        *p_font = p_new;    }    else    {        font_stack_t *p_last;        for( p_last = *p_font;             p_last->p_next;             p_last = p_last->p_next )        ;        p_last->p_next = p_new;    }    return VLC_SUCCESS;}static int PopFont( font_stack_t **p_font ){    font_stack_t *p_last, *p_next_to_last;    if( !p_font || !*p_font )        return VLC_EGENERIC;    p_next_to_last = NULL;    for( p_last = *p_font;         p_last->p_next;         p_last = p_last->p_next )    {        p_next_to_last = p_last;    }    if( p_next_to_last )        p_next_to_last->p_next = NULL;    else        *p_font = NULL;    free( p_last->psz_name );    free( p_last );    return VLC_SUCCESS;}static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size,                     uint32_t *i_color ){    font_stack_t *p_last;    if( !p_font || !*p_font )        return VLC_EGENERIC;    for( p_last=*p_font;         p_last->p_next;         p_last=p_last->p_next )    ;    *psz_name = p_last->psz_name;    *i_size   = p_last->i_size;    *i_color  = p_last->i_color;    return VLC_SUCCESS;}static ATSUStyle GetStyleFromFontStack( filter_sys_t *p_sys,        font_stack_t **p_fonts, bool b_bold, bool b_italic,        bool b_uline ){    ATSUStyle   p_style = NULL;    char     *psz_fontname = NULL;    uint32_t  i_font_color = p_sys->i_font_color;    int       i_font_size  = p_sys->i_font_size;    if( VLC_SUCCESS == PeekFont( p_fonts, &psz_fontname, &i_font_size,                                 &i_font_color ))    {        p_style = CreateStyle( psz_fontname, i_font_size, i_font_color,                               b_bold, b_italic, b_uline );    }    return p_style;}static int HandleFontAttributes( xml_reader_t *p_xml_reader,                                  font_stack_t **p_fonts, int i_scale ){    int        rv;    char      *psz_fontname = NULL;    uint32_t   i_font_color = 0xffffff;    int        i_font_alpha = 0;    int        i_font_size  = 24;    // Default all attributes to the top font in the stack -- in case not    // all attributes are specified in the sub-font    if( VLC_SUCCESS == PeekFont( p_fonts,                                 &psz_fontname,                                 &i_font_size,                                 &i_font_color ))    {        psz_fontname = strdup( psz_fontname );        i_font_size = i_font_size * 1000 / i_scale;    }    i_font_alpha = (i_font_color >> 24) & 0xff;    i_font_color &= 0x00ffffff;    while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS )    {        char *psz_name = xml_ReaderName( p_xml_reader );        char *psz_value = xml_ReaderValue( p_xml_reader );        if( psz_name && psz_value )        {            if( !strcasecmp( "face", psz_name ) )            {                free( psz_fontname );                psz_fontname = strdup( psz_value );            }            else if( !strcasecmp( "size", psz_name ) )            {                if( ( *psz_value == '+' ) || ( *psz_value == '-' ) )                {                    int i_value = atoi( psz_value );                    if( ( i_value >= -5 ) && ( i_value <= 5 ) )                        i_font_size += ( i_value * i_font_size ) / 10;                    else if( i_value < -5 )                        i_font_size = - i_value;                    else if( i_value > 5 )                        i_font_size = i_value;                }                else                    i_font_size = atoi( psz_value );            }            else if( !strcasecmp( "color", psz_name )  &&                     ( psz_value[0] == '#' ) )            {                i_font_color = strtol( psz_value + 1, NULL, 16 );                i_font_color &= 0x00ffffff;            }            else if( !strcasecmp( "alpha", psz_name ) &&                     ( psz_value[0] == '#' ) )            {                i_font_alpha = strtol( psz_value + 1, NULL, 16 );                i_font_alpha &= 0xff;            }        }        free( psz_name );        free( psz_value );    }    rv = PushFont( p_fonts,                   psz_fontname,                   i_font_size * i_scale / 1000,                   (i_font_color & 0xffffff) | ((i_font_alpha & 0xff) << 24) );    free( psz_fontname );    return rv;}static int ProcessNodes( filter_t *p_filter,                         xml_reader_t *p_xml_reader,                         text_style_t *p_font_style,                         UniChar *psz_text,                         int *pi_len,                         uint32_t *pi_runs,                         uint32_t **ppi_run_lengths,                         ATSUStyle **ppp_styles ){    int           rv             = VLC_SUCCESS;    filter_sys_t *p_sys          = p_filter->p_sys;    UniChar      *psz_text_orig  = psz_text;    font_stack_t *p_fonts        = NULL;    vlc_value_t   val;    int           i_scale        = 1000;    char *psz_node  = NULL;    bool b_italic = false;    bool b_bold   = false;    bool b_uline  = false;    if( VLC_SUCCESS == var_Get( p_filter, "scale", &val ))        i_scale = val.i_int;    if( p_font_style )    {        rv = PushFont( &p_fonts,               p_font_style->psz_fontname,               p_font_style->i_font_size * i_scale / 1000,               (p_font_style->i_font_color & 0xffffff) |                   ((p_font_style->i_font_alpha & 0xff) << 24) );        if( p_font_style->i_style_flags & STYLE_BOLD )            b_bold = true;        if( p_font_style->i_style_flags & STYLE_ITALIC )            b_italic = true;        if( p_font_style->i_style_flags & STYLE_UNDERLINE )            b_uline = true;    }    else    {        rv = PushFont( &p_fonts,                       p_sys->psz_font_name,                       p_sys->i_font_size,                       p_sys->i_font_color );    }    if( rv != VLC_SUCCESS )        return rv;    while ( ( xml_ReaderRead( p_xml_reader ) == 1 ) )    {        switch ( xml_ReaderNodeType( p_xml_reader ) )        {            case XML_READER_NONE:                break;            case XML_READER_ENDELEM:                psz_node = xml_ReaderName( p_xml_reader );                if( psz_node )                {                    if( !strcasecmp( "font", psz_node ) )                        PopFont( &p_fonts );                    else if( !strcasecmp( "b", psz_node ) )                        b_bold   = false;                    else if( !strcasecmp( "i", psz_node ) )                        b_italic = false;                    else if( !strcasecmp( "u", psz_node ) )                        b_uline  = false;                    free( psz_node );                }                break;            case XML_READER_STARTELEM:                psz_node = xml_ReaderName( p_xml_reader );                if( psz_node )                {                    if( !strcasecmp( "font", psz_node ) )                        rv = HandleFontAttributes( p_xml_reader, &p_fonts, i_scale );                    else if( !strcasecmp( "b", psz_node ) )                        b_bold = true;                    else if( !strcasecmp( "i", psz_node ) )                        b_italic = true;                    else if( !strcasecmp( "u", psz_node ) )                        b_uline = true;                    else if( !strcasecmp( "br", psz_node ) )                    {                        uint32_t i_string_length;                        ConvertToUTF16( "\n", &i_string_length, &psz_text );                        psz_text += i_string_length;                        (*pi_runs)++;                        if( *ppp_styles )                            *ppp_styles = (ATSUStyle *) realloc( *ppp_styles, *pi_runs * sizeof( ATSUStyle ) );                        else                            *ppp_styles = (ATSUStyle *) malloc( *pi_runs * sizeof( ATSUStyle ) );                        (*ppp_styles)[ *pi_runs - 1 ] = GetStyleFromFontStack( p_sys, &p_fonts, b_bold, b_italic, b_uline );                        if( *ppi_run_lengths )                            *ppi_run_lengths = (uint32_t *) realloc( *ppi_run_lengths, *pi_runs * sizeof( uint32_t ) );                        else                            *ppi_run_lengths = (uint32_t *) malloc( *pi_runs * sizeof( uint32_t ) );                        (*ppi_run_lengths)[ *pi_runs - 1 ] = i_string_length;                    }                    free( psz_node );                }                break;            case XML_READER_TEXT:                psz_node = xml_ReaderValue( p_xml_reader );                if( psz_node )                {

⌨️ 快捷键说明

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