📄 svg.c
字号:
int channels_in; int alpha; picture_t *p_pic; subpicture_region_t *p_region_tmp; if ( p_filter->p_sys->i_width != i_width || p_filter->p_sys->i_height != i_height ) { svg_set_size( p_filter, i_width, i_height ); p_svg->p_rendition = NULL; } if( p_svg->p_rendition == NULL ) { svg_RenderPicture( p_filter, p_svg ); if( ! p_svg->p_rendition ) { msg_Err( p_filter, "Cannot render SVG" ); return VLC_EGENERIC; } } i_width = gdk_pixbuf_get_width( p_svg->p_rendition ); i_height = gdk_pixbuf_get_height( p_svg->p_rendition ); /* Create a new subpicture region */ memset( &fmt, 0, sizeof( video_format_t ) ); fmt.i_chroma = VLC_FOURCC( 'Y','U','V','A' ); fmt.i_aspect = VOUT_ASPECT_FACTOR; fmt.i_width = fmt.i_visible_width = i_width; fmt.i_height = fmt.i_visible_height = i_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 ); p_region->i_x = p_region->i_y = 0; p_y = p_region->picture.Y_PIXELS; p_u = p_region->picture.U_PIXELS; p_v = p_region->picture.V_PIXELS; p_a = p_region->picture.A_PIXELS; i_pitch = p_region->picture.Y_PITCH; i_u_pitch = p_region->picture.U_PITCH; /* Initialize the region pixels (only the alpha will be changed later) */ memset( p_y, 0x00, i_pitch * p_region->fmt.i_height ); memset( p_u, 0x80, i_u_pitch * p_region->fmt.i_height ); memset( p_v, 0x80, i_u_pitch * p_region->fmt.i_height ); p_pic = &p_region->picture; /* Copy the data */ /* This rendering code is in no way optimized. If someone has some time to make it work faster or better, please do. */ /* p_pixbuf->get_rowstride() is the number of bytes in a line. p_pixbuf->get_height() is the number of lines. The number of bytes of p_pixbuf->p_pixels is get_rowstride * get_height if( has_alpha() ) { alpha = pixels [ n_channels * ( y*rowstride + x ) + 3 ]; } red = pixels [ n_channels * ( y*rowstride ) + x ) ]; green = pixels [ n_channels * ( y*rowstride ) + x ) + 1 ]; blue = pixels [ n_channels * ( y*rowstride ) + x ) + 2 ]; */ pixels_in = gdk_pixbuf_get_pixels( p_svg->p_rendition ); rowstride_in = gdk_pixbuf_get_rowstride( p_svg->p_rendition ); channels_in = gdk_pixbuf_get_n_channels( p_svg->p_rendition ); alpha = gdk_pixbuf_get_has_alpha( p_svg->p_rendition ); /* This crashes the plugin (if !alpha). As there is always an alpha value, it does not matter for the moment : if( !alpha ) memset( p_a, 0xFF, i_pitch * p_region->fmt.i_height ); */#define INDEX_IN( x, y ) ( y * rowstride_in + x * channels_in )#define INDEX_OUT( x, y ) ( y * i_pitch + x * p_pic->p[Y_PLANE].i_pixel_pitch ) for( y = 0; y < i_height; y++ ) { for( x = 0; x < i_width; x++ ) { guchar *p_in; int i_out; p_in = &pixels_in[INDEX_IN( x, y )];#define R( pixel ) *pixel#define G( pixel ) *( pixel+1 )#define B( pixel ) *( pixel+2 )#define ALPHA( pixel ) *( pixel+3 ) /* From http://www.geocrawler.com/archives/3/8263/2001/6/0/6020594/ : Y = 0.29900 * R + 0.58700 * G + 0.11400 * B U = -0.1687 * r - 0.3313 * g + 0.5 * b + 128 V = 0.5 * r - 0.4187 * g - 0.0813 * b + 128 */ if ( alpha ) { i_out = INDEX_OUT( x, y ); p_pic->Y_PIXELS[i_out] = .299 * R( p_in ) + .587 * G( p_in ) + .114 * B( p_in ); p_pic->U_PIXELS[i_out] = -.1687 * R( p_in ) - .3313 * G( p_in ) + .5 * B( p_in ) + 128; p_pic->V_PIXELS[i_out] = .5 * R( p_in ) - .4187 * G( p_in ) - .0813 * B( p_in ) + 128; p_pic->A_PIXELS[i_out] = ALPHA( p_in ); } } } return VLC_SUCCESS;}static void svg_set_size( filter_t *p_filter, int width, int height ){ p_filter->p_sys->i_width = width; p_filter->p_sys->i_height = height;}static void svg_SizeCallback( int *width, int *height, gpointer data ){ filter_t *p_filter = data; *width = p_filter->p_sys->i_width; *height = p_filter->p_sys->i_height; return;}static void svg_RenderPicture( filter_t *p_filter, svg_rendition_t *p_svg ){ /* Render the SVG string p_string->psz_text into a new picture_t p_string->p_rendition with dimensions ( ->i_width, ->i_height ) */ RsvgHandle *p_handle; GError *error = NULL; p_svg->p_rendition = NULL; p_handle = rsvg_handle_new(); if( !p_handle ) { msg_Err( p_filter, "Error creating SVG reader: %s", error->message ); return; } rsvg_handle_set_size_callback( p_handle, svg_SizeCallback, p_filter, NULL ); if( ! rsvg_handle_write( p_handle, ( guchar* )p_svg->psz_text, strlen( p_svg->psz_text ), &error ) ) { msg_Err( p_filter, "error while rendering SVG: %s\n", error->message ); g_object_unref( G_OBJECT( p_handle ) ); return; } if( ! rsvg_handle_close( p_handle, &error ) ) { msg_Err( p_filter, "error while rendering SVG (close): %s\n", error->message ); g_object_unref( G_OBJECT( p_handle ) ); return; } p_svg->p_rendition = rsvg_handle_get_pixbuf( p_handle ); g_object_unref( G_OBJECT( p_handle ) );}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; svg_rendition_t *p_svg = NULL; char *psz_string; /* 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; p_svg = ( svg_rendition_t * )malloc( sizeof( svg_rendition_t ) ); if( !p_svg ) return VLC_ENOMEM; p_region_out->i_x = p_region_in->i_x; p_region_out->i_y = p_region_in->i_y; /* Check if the data is SVG or pure text. In the latter case, convert the text to SVG. FIXME: find a better test */ if( strstr( psz_string, "<svg" )) { /* Data is SVG: duplicate */ p_svg->psz_text = strdup( psz_string ); if( !p_svg->psz_text ) { free( p_svg ); return VLC_ENOMEM; } } else { /* Data is text. Convert to SVG */ /* FIXME: handle p_style attributes */ int length; char* psz_template = p_sys->psz_template; length = strlen( psz_string ) + strlen( psz_template ) + 42; p_svg->psz_text = malloc( ( length + 1 ) * sizeof( char ) ); if( !p_svg->psz_text ) { free( p_svg ); return VLC_ENOMEM; } memset( p_svg->psz_text, 0, length + 1 ); snprintf( p_svg->psz_text, length, psz_template, psz_string ); } p_svg->i_width = p_sys->i_width; p_svg->i_height = p_sys->i_height; p_svg->i_chroma = VLC_FOURCC( 'Y','U','V','A' ); /* Render the SVG. The input data is stored in the p_string structure, and the function updates the p_rendition attribute. */ svg_RenderPicture( p_filter, p_svg ); Render( p_filter, p_region_out, p_svg, p_svg->i_width, p_svg->i_height ); FreeString( p_svg ); return VLC_SUCCESS;}static void FreeString( svg_rendition_t *p_svg ){ free( p_svg->psz_text ); /* p_svg->p_rendition is a GdkPixbuf, and its allocation is managed through ref. counting */ if( p_svg->p_rendition ) g_object_unref( p_svg->p_rendition ); free( p_svg );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -