win32text.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:16k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * win32text.c : Text drawing routines using the TextOut win32 API
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 - 2009 the VideoLAN team
  5.  * $Id: 27e12f875d464adaa4b2196c600f9f44d35f6bae $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@videolan.org>
  8.  *          Pierre Ynard
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_vout.h>
  33. #include <vlc_osd.h>
  34. #include <vlc_block.h>
  35. #include <vlc_filter.h>
  36. #include <math.h>
  37. /*****************************************************************************
  38.  * Local prototypes
  39.  *****************************************************************************/
  40. static int  Create ( vlc_object_t * );
  41. static void Destroy( vlc_object_t * );
  42. /* The RenderText call maps to pf_render_string, defined in vlc_filter.h */
  43. static int RenderText( filter_t *, subpicture_region_t *,
  44.                        subpicture_region_t * );
  45. static int Render( filter_t *, subpicture_region_t *, uint8_t *, int, int);
  46. static int SetFont( filter_t *, int );
  47. /*****************************************************************************
  48.  * Module descriptor
  49.  *****************************************************************************/
  50. #define FONT_TEXT N_("Font")
  51. #define FONT_LONGTEXT N_("Filename for the font you want to use")
  52. #define FONTSIZE_TEXT N_("Font size in pixels")
  53. #define FONTSIZE_LONGTEXT N_("This is the default size of the fonts " 
  54.      "that will be rendered on the video. " 
  55.      "If set to something different than 0 this option will override the " 
  56.      "relative font size." )
  57. #define OPACITY_TEXT N_("Opacity")
  58. #define OPACITY_LONGTEXT N_("The opacity (inverse of transparency) of the " 
  59.      "text that will be rendered on the video. 0 = transparent, " 
  60.      "255 = totally opaque. " )
  61. #define COLOR_TEXT N_("Text default color")
  62. #define COLOR_LONGTEXT N_("The color of the text that will be rendered on "
  63.   "the video. This must be an hexadecimal (like HTML colors). The first two "
  64.   "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"
  65.   " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" )
  66. #define FONTSIZER_TEXT N_("Relative font size")
  67. #define FONTSIZER_LONGTEXT N_("This is the relative default size of the " 
  68.   "fonts that will be rendered on the video. If absolute font size is set, "
  69.    "relative size will be overriden." )
  70. static int const pi_sizes[] = { 20, 18, 16, 12, 6 };
  71. static char *const ppsz_sizes_text[] = {
  72.     N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") };
  73. static const int pi_color_values[] = {
  74.   0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000,
  75.   0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00808000, 0x00008000, 0x00008080,
  76.   0x0000FF00, 0x00800080, 0x00000080, 0x000000FF, 0x0000FFFF };
  77. static const char *const ppsz_color_descriptions[] = {
  78.   N_("Black"), N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"),
  79.   N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"), N_("Teal"),
  80.   N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"), N_("Aqua") };
  81. vlc_module_begin ()
  82.     set_shortname( N_("Text renderer"))
  83.     set_description( N_("Win32 font renderer") )
  84.     set_category( CAT_VIDEO )
  85.     set_subcategory( SUBCAT_VIDEO_SUBPIC )
  86.     add_integer( "win32text-fontsize", 0, NULL, FONTSIZE_TEXT,
  87.                  FONTSIZE_LONGTEXT, true )
  88.     /* opacity valid on 0..255, with default 255 = fully opaque */
  89.     add_integer_with_range( "win32-opacity", 255, 0, 255, NULL,
  90.         OPACITY_TEXT, OPACITY_LONGTEXT, false )
  91.     /* hook to the color values list, with default 0x00ffffff = white */
  92.     add_integer( "win32text-color", 0x00FFFFFF, NULL, COLOR_TEXT,
  93.                  COLOR_LONGTEXT, true )
  94.         change_integer_list( pi_color_values, ppsz_color_descriptions, NULL );
  95.     add_integer( "win32text-rel-fontsize", 16, NULL, FONTSIZER_TEXT,
  96.                  FONTSIZER_LONGTEXT, false )
  97.         change_integer_list( pi_sizes, ppsz_sizes_text, NULL );
  98.     set_capability( "text renderer", 50 )
  99.     add_shortcut( "text" )
  100.     set_callbacks( Create, Destroy )
  101. vlc_module_end ()
  102. /*****************************************************************************
  103.  * filter_sys_t: win32text local data
  104.  *****************************************************************************/
  105. struct filter_sys_t
  106. {
  107.     uint8_t        i_font_opacity;
  108.     int            i_font_color;
  109.     int            i_font_size;
  110.     int            i_default_font_size;
  111.     int            i_display_height;
  112.     HDC hcdc;
  113.     HFONT hfont;
  114.     HFONT hfont_bak;
  115.     int i_logpy;
  116. };
  117. static const uint8_t pi_gamma[16] =
  118.   {0x00, 0x41, 0x52, 0x63, 0x84, 0x85, 0x96, 0xa7, 0xb8, 0xc9,
  119.    0xca, 0xdb, 0xdc, 0xed, 0xee, 0xff};
  120. /*****************************************************************************
  121.  * Create: creates the module
  122.  *****************************************************************************/
  123. static int Create( vlc_object_t *p_this )
  124. {
  125.     filter_t *p_filter = (filter_t *)p_this;
  126.     filter_sys_t *p_sys;
  127.     char *psz_fontfile = NULL;
  128.     vlc_value_t val;
  129.     HDC hdc;
  130.     /* Allocate structure */
  131.     p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) );
  132.     if( !p_sys )
  133.         return VLC_ENOMEM;
  134.     p_sys->i_font_size = 0;
  135.     p_sys->i_display_height = 0;
  136.     var_Create( p_filter, "win32text-font",
  137.                 VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  138.     var_Create( p_filter, "win32text-fontsize",
  139.                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  140.     var_Create( p_filter, "win32text-rel-fontsize",
  141.                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  142.     var_Create( p_filter, "win32text-opacity",
  143.                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  144.     var_Get( p_filter, "win32text-opacity", &val );
  145.     p_sys->i_font_opacity = __MAX( __MIN( val.i_int, 255 ), 0 );
  146.     var_Create( p_filter, "win32text-color",
  147.                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  148.     var_Get( p_filter, "win32text-color", &val );
  149.     p_sys->i_font_color = __MAX( __MIN( val.i_int, 0xFFFFFF ), 0 );
  150.     p_sys->hfont = p_sys->hfont_bak = 0;
  151.     hdc = GetDC( NULL );
  152.     p_sys->hcdc = CreateCompatibleDC( hdc );
  153.     p_sys->i_logpy = GetDeviceCaps( hdc, LOGPIXELSY );
  154.     ReleaseDC( NULL, hdc );
  155.     SetBkMode( p_sys->hcdc, TRANSPARENT );
  156.     var_Get( p_filter, "win32text-fontsize", &val );
  157.     p_sys->i_default_font_size = val.i_int;
  158.     if( SetFont( p_filter, 0 ) != VLC_SUCCESS ) goto error;
  159.     free( psz_fontfile );
  160.     p_filter->pf_render_text = RenderText;
  161.     p_filter->pf_render_html = NULL;
  162.     return VLC_SUCCESS;
  163.  error:
  164.     free( psz_fontfile );
  165.     free( p_sys );
  166.     return VLC_EGENERIC;
  167. }
  168. /*****************************************************************************
  169.  * Destroy: destroy the module
  170.  *****************************************************************************/
  171. static void Destroy( vlc_object_t *p_this )
  172. {
  173.     filter_t *p_filter = (filter_t *)p_this;
  174.     filter_sys_t *p_sys = p_filter->p_sys;
  175.     if( p_sys->hfont_bak ) SelectObject( p_sys->hcdc, p_sys->hfont_bak );
  176.     if( p_sys->hfont ) DeleteObject( p_sys->hfont );
  177.     DeleteDC( p_sys->hcdc );
  178.     free( p_sys );
  179. }
  180. /*****************************************************************************
  181.  * Render: place string in picture
  182.  *****************************************************************************
  183.  * This function merges the previously rendered win32text glyphs into a picture
  184.  *****************************************************************************/
  185. static int Render( filter_t *p_filter, subpicture_region_t *p_region,
  186.                    uint8_t *p_bitmap, int i_width, int i_height )
  187. {
  188.     uint8_t *p_dst;
  189.     video_format_t fmt;
  190.     int i, i_pitch;
  191.     bool b_outline = true;
  192.     /* Create a new subpicture region */
  193.     memset( &fmt, 0, sizeof(video_format_t) );
  194.     fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
  195.     fmt.i_width = fmt.i_visible_width = i_width + (b_outline ? 4 : 0);
  196.     fmt.i_height = fmt.i_visible_height = i_height + (b_outline ? 4 : 0);
  197.     fmt.i_x_offset = fmt.i_y_offset = 0;
  198.     /* Build palette */
  199.     fmt.p_palette = calloc( 1, sizeof(*fmt.p_palette) );
  200.     if( !fmt.p_palette )
  201.         return VLC_EGENERIC;
  202.     fmt.p_palette->i_entries = 16;
  203.     for( i = 0; i < fmt.p_palette->i_entries; i++ )
  204.     {
  205.         fmt.p_palette->palette[i][0] = pi_gamma[i];
  206.         fmt.p_palette->palette[i][1] = 128;
  207.         fmt.p_palette->palette[i][2] = 128;
  208.         fmt.p_palette->palette[i][3] = pi_gamma[i];
  209.     }
  210.     p_region->p_picture = picture_New( fmt.i_chroma, fmt.i_width, fmt.i_height, fmt.i_aspect );
  211.     if( !p_region->p_picture )
  212.     {
  213.         free( fmt.p_palette );
  214.         return VLC_EGENERIC;
  215.     }
  216.     p_region->fmt = fmt;
  217.     p_dst = p_region->p_picture->Y_PIXELS;
  218.     i_pitch = p_region->p_picture->Y_PITCH;
  219.     if( b_outline )
  220.     {
  221.         memset( p_dst, 0, i_pitch * fmt.i_height );
  222.         p_dst += p_region->p_picture->Y_PITCH * 2 + 2;
  223.     }
  224.     for( i = 0; i < i_height; i++ )
  225.     {
  226.         memcpy( p_dst, p_bitmap, i_width );
  227.         p_bitmap += (i_width+3) & ~3;
  228.         p_dst += i_pitch;
  229.     }
  230.     /* Outlining (find something better than nearest neighbour filtering ?) */
  231.     if( b_outline )
  232.     {
  233.         uint8_t *p_top = p_dst; /* Use 1st line as a cache */
  234.         uint8_t left, current;
  235.         int x, y;
  236.         p_dst = p_region->p_picture->Y_PIXELS;
  237.         for( y = 1; y < (int)fmt.i_height - 1; y++ )
  238.         {
  239.             memcpy( p_top, p_dst, fmt.i_width );
  240.             p_dst += i_pitch;
  241.             left = 0;
  242.             for( x = 1; x < (int)fmt.i_width - 1; x++ )
  243.             {
  244.                 current = p_dst[x];
  245.                 p_dst[x] = ( 4 * (int)p_dst[x] + left + p_top[x] + p_dst[x+1] +
  246.                              p_dst[x + i_pitch]) / 8;
  247.                 left = current;
  248.             }
  249.         }
  250.         memset( p_top, 0, fmt.i_width );
  251.     }
  252.     return VLC_SUCCESS;
  253. }
  254. static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
  255.                        subpicture_region_t *p_region_in )
  256. {
  257.     filter_sys_t *p_sys = p_filter->p_sys;
  258.     int i_font_color, i_font_alpha, i_font_size;
  259.     uint8_t *p_bitmap;
  260.     TCHAR *psz_string;
  261.     int i, i_width, i_height;
  262.     HBITMAP bitmap, bitmap_bak;
  263.     BITMAPINFO *p_bmi;
  264.     RECT rect = { 0, 0, 0, 0 };
  265.     /* Sanity check */
  266.     if( !p_region_in || !p_region_out ) return VLC_EGENERIC;
  267.     if( !p_region_in->psz_text || !*p_region_in->psz_text )
  268.         return VLC_EGENERIC;
  269.     psz_string = malloc( (strlen( p_region_in->psz_text )+1) * sizeof(TCHAR) );
  270.     if( !psz_string )
  271.         return VLC_ENOMEM;
  272. #ifdef UNICODE
  273.     if( mbstowcs( psz_string, p_region_in->psz_text,
  274.                   strlen( p_region_in->psz_text ) * sizeof(TCHAR) ) < 0 )
  275.     {
  276.         free( psz_string );
  277.         return VLC_EGENERIC;
  278.     }
  279. #else
  280.     strcpy( psz_string, p_region_in->psz_text );
  281. #endif
  282.     if( !*psz_string )
  283.     {
  284.         free( psz_string );
  285.         return VLC_EGENERIC;
  286.     }
  287.     if( p_region_in->p_style )
  288.     {
  289.         i_font_color = __MAX( __MIN( p_region_in->p_style->i_font_color, 0xFFFFFF ), 0 );
  290.         i_font_alpha = __MAX( __MIN( p_region_in->p_style->i_font_alpha, 255 ), 0 );
  291.         i_font_size  = __MAX( __MIN( p_region_in->p_style->i_font_size, 255 ), 0 );
  292.     }
  293.     else
  294.     {
  295.         i_font_color = p_sys->i_font_color;
  296.         i_font_alpha = 255 - p_sys->i_font_opacity;
  297.         i_font_size = p_sys->i_default_font_size;
  298.     }
  299.     SetFont( p_filter, i_font_size );
  300.     SetTextColor( p_sys->hcdc, RGB( (i_font_color >> 16) & 0xff,
  301.                   (i_font_color >> 8) & 0xff, i_font_color & 0xff) );
  302.     DrawText( p_sys->hcdc, psz_string, -1, &rect,
  303.               DT_CALCRECT | DT_CENTER | DT_NOPREFIX );
  304.     i_width = rect.right; i_height = rect.bottom;
  305.     p_bmi = malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*16);
  306.     memset( p_bmi, 0, sizeof(BITMAPINFOHEADER) );
  307.     p_bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  308.     p_bmi->bmiHeader.biWidth = (i_width+3) & ~3;
  309.     p_bmi->bmiHeader.biHeight = - i_height;
  310.     p_bmi->bmiHeader.biPlanes = 1;
  311.     p_bmi->bmiHeader.biBitCount = 8;
  312.     p_bmi->bmiHeader.biCompression = BI_RGB;
  313.     p_bmi->bmiHeader.biClrUsed = 16;
  314.     for( i = 0; i < 16; i++ )
  315.     {
  316.         p_bmi->bmiColors[i].rgbBlue =
  317.             p_bmi->bmiColors[i].rgbGreen =
  318.                 p_bmi->bmiColors[i].rgbRed = pi_gamma[i];
  319.     }
  320.     bitmap = CreateDIBSection( p_sys->hcdc, p_bmi, DIB_RGB_COLORS,
  321.                                (void **)&p_bitmap, NULL, 0 );
  322.     if( !bitmap )
  323.     {
  324.         msg_Err( p_filter, "could not create bitmap" );
  325.         free( psz_string );
  326.         return VLC_EGENERIC;
  327.     }
  328.     bitmap_bak = SelectObject( p_sys->hcdc, bitmap );
  329.     FillRect( p_sys->hcdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
  330.     if( !DrawText( p_sys->hcdc, psz_string, -1, &rect,
  331.                    DT_CENTER | DT_NOPREFIX ) )
  332.     {
  333.         msg_Err( p_filter, "could not draw text" );
  334.     }
  335.     p_region_out->i_x = p_region_in->i_x;
  336.     p_region_out->i_y = p_region_in->i_y;
  337.     Render( p_filter, p_region_out, p_bitmap, i_width, i_height );
  338.     SelectObject( p_sys->hcdc, bitmap_bak );
  339.     DeleteObject( bitmap );
  340.     free( psz_string );
  341.     return VLC_SUCCESS;
  342. }
  343. static int SetFont( filter_t *p_filter, int i_size )
  344. {
  345.     filter_sys_t *p_sys = p_filter->p_sys;
  346.     LOGFONT logfont;
  347.     if( i_size && i_size == p_sys->i_font_size ) return VLC_SUCCESS;
  348.     if( !i_size )
  349.     {
  350.         vlc_value_t val;
  351.         if( !p_sys->i_default_font_size &&
  352.             p_sys->i_display_height == (int)p_filter->fmt_out.video.i_height )
  353.             return VLC_SUCCESS;
  354.         if( p_sys->i_default_font_size )
  355.         {
  356.             i_size = p_sys->i_default_font_size;
  357.         }
  358.         else
  359.         {
  360.             var_Get( p_filter, "win32text-rel-fontsize", &val );
  361.             i_size = (int)p_filter->fmt_out.video.i_height / val.i_int;
  362.             p_filter->p_sys->i_display_height =
  363.                 p_filter->fmt_out.video.i_height;
  364.         }
  365.         if( i_size <= 0 )
  366.         {
  367.             msg_Warn( p_filter, "invalid fontsize, using 12" );
  368.             i_size = 12;
  369.         }
  370.         msg_Dbg( p_filter, "using fontsize: %i", i_size );
  371.     }
  372.     p_sys->i_font_size = i_size;
  373.     if( p_sys->hfont_bak ) SelectObject( p_sys->hcdc, p_sys->hfont_bak );
  374.     if( p_sys->hfont ) DeleteObject( p_sys->hfont );
  375.     i_size = i_size * (int64_t)p_sys->i_logpy / 72;
  376.     logfont.lfHeight = i_size;
  377.     logfont.lfWidth = 0;
  378.     logfont.lfEscapement = 0;
  379.     logfont.lfOrientation = 0;
  380.     logfont.lfWeight = 0;
  381.     logfont.lfItalic = FALSE;
  382.     logfont.lfUnderline = FALSE;
  383.     logfont.lfStrikeOut = FALSE;
  384.     logfont.lfCharSet = ANSI_CHARSET;
  385.     logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  386.     logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  387.     logfont.lfQuality = ANTIALIASED_QUALITY;
  388.     logfont.lfPitchAndFamily = DEFAULT_PITCH;
  389.     memcpy( logfont.lfFaceName, _T("Arial"), sizeof(_T("Arial")) );
  390.     p_sys->hfont = CreateFontIndirect( &logfont );
  391.     p_sys->hfont_bak = SelectObject( p_sys->hcdc, p_sys->hfont );
  392.     return VLC_SUCCESS;
  393. }