Commit 234c3fab authored by Felix Paul Kühne's avatar Felix Paul Kühne

quartztext: unify and modernize coding style

parent da06d2cb
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/ *****************************************************************************/
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// Preamble * Preamble
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
...@@ -57,47 +57,47 @@ ...@@ -57,47 +57,47 @@
#define VERTICAL_MARGIN 3 #define VERTICAL_MARGIN 3
#define HORIZONTAL_MARGIN 10 #define HORIZONTAL_MARGIN 10
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// Local prototypes * Local prototypes
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
static int Create ( vlc_object_t * ); static int Create (vlc_object_t *);
static void Destroy( vlc_object_t * ); static void Destroy(vlc_object_t *);
static int LoadFontsFromAttachments( filter_t *p_filter ); static int LoadFontsFromAttachments(filter_t *p_filter);
static int RenderText( filter_t *, subpicture_region_t *, static int RenderText(filter_t *, subpicture_region_t *,
subpicture_region_t *, subpicture_region_t *,
const vlc_fourcc_t * ); const vlc_fourcc_t *);
static int RenderHtml( filter_t *, subpicture_region_t *, static int RenderHtml(filter_t *, subpicture_region_t *,
subpicture_region_t *, subpicture_region_t *,
const vlc_fourcc_t * ); const vlc_fourcc_t *);
static int GetFontSize( filter_t *p_filter ); static int GetFontSize(filter_t *p_filter);
static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, static int RenderYUVA(filter_t *p_filter, subpicture_region_t *p_region,
CFMutableAttributedStringRef p_attrString ); CFMutableAttributedStringRef p_attrString);
static void setFontAttibutes( char *psz_fontname, int i_font_size, uint32_t i_font_color, static void setFontAttibutes(char *psz_fontname, int i_font_size, uint32_t i_font_color,
bool b_bold, bool b_italic, bool b_underline, bool b_bold, bool b_italic, bool b_underline,
CFRange p_range, CFMutableAttributedStringRef p_attrString ); CFRange p_range, CFMutableAttributedStringRef p_attrString);
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// Module descriptor * Module descriptor
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
// The preferred way to set font style information is for it to come from the /* The preferred way to set font style information is for it to come from the
// subtitle file, and for it to be rendered with RenderHtml instead of * subtitle file, and for it to be rendered with RenderHtml instead of
// RenderText. * RenderText. */
#define FONT_TEXT N_("Font") #define FONT_TEXT N_("Font")
#define FONT_LONGTEXT N_("Name for the font you want to use") #define FONT_LONGTEXT N_("Name for the font you want to use")
#define FONTSIZER_TEXT N_("Relative font size") #define FONTSIZER_TEXT N_("Relative font size")
#define FONTSIZER_LONGTEXT N_("This is the relative default size of the " \ #define FONTSIZER_LONGTEXT N_("This is the relative default size of the " \
"fonts that will be rendered on the video. If absolute font size is set, "\ "fonts that will be rendered on the video. If absolute font size is set, "\
"relative size will be overridden." ) "relative size will be overridden.")
#define COLOR_TEXT N_("Text default color") #define COLOR_TEXT N_("Text default color")
#define COLOR_LONGTEXT N_("The color of the text that will be rendered on "\ #define COLOR_LONGTEXT N_("The color of the text that will be rendered on "\
"the video. This must be an hexadecimal (like HTML colors). The first two "\ "the video. This must be an hexadecimal (like HTML colors). The first two "\
"chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\ "chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\
" #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" ) " #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white")
static const int pi_color_values[] = { static const int pi_color_values[] = {
0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000, 0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000,
...@@ -114,22 +114,22 @@ static const char *const ppsz_sizes_text[] = { ...@@ -114,22 +114,22 @@ static const char *const ppsz_sizes_text[] = {
N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") }; N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") };
vlc_module_begin () vlc_module_begin ()
set_shortname( N_("Text renderer for Mac")) set_shortname(N_("Text renderer for Mac"))
set_description( N_("CoreText font renderer") ) set_description(N_("CoreText font renderer"))
set_category( CAT_VIDEO ) set_category(CAT_VIDEO)
set_subcategory( SUBCAT_VIDEO_SUBPIC ) set_subcategory(SUBCAT_VIDEO_SUBPIC)
add_string( "quartztext-font", DEFAULT_FONT, FONT_TEXT, FONT_LONGTEXT, add_string("quartztext-font", DEFAULT_FONT, FONT_TEXT, FONT_LONGTEXT,
false ) false)
add_integer( "quartztext-rel-fontsize", DEFAULT_REL_FONT_SIZE, FONTSIZER_TEXT, add_integer("quartztext-rel-fontsize", DEFAULT_REL_FONT_SIZE, FONTSIZER_TEXT,
FONTSIZER_LONGTEXT, false ) FONTSIZER_LONGTEXT, false)
change_integer_list( pi_sizes, ppsz_sizes_text ) change_integer_list(pi_sizes, ppsz_sizes_text)
add_integer( "quartztext-color", 0x00FFFFFF, COLOR_TEXT, add_integer("quartztext-color", 0x00FFFFFF, COLOR_TEXT,
COLOR_LONGTEXT, false ) COLOR_LONGTEXT, false)
change_integer_list( pi_color_values, ppsz_color_descriptions ) change_integer_list(pi_color_values, ppsz_color_descriptions)
set_capability( "text renderer", 50 ) set_capability("text renderer", 50)
add_shortcut( "text" ) add_shortcut("text")
set_callbacks( Create, Destroy ) set_callbacks(Create, Destroy)
vlc_module_end () vlc_module_end ()
typedef struct font_stack_t font_stack_t; typedef struct font_stack_t font_stack_t;
...@@ -162,12 +162,12 @@ struct offscreen_bitmap_t ...@@ -162,12 +162,12 @@ struct offscreen_bitmap_t
int i_bytesPerRow; int i_bytesPerRow;
}; };
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// filter_sys_t: quartztext local data * filter_sys_t: quartztext local data
////////////////////////////////////////////////////////////////////////////// *****************************************************************************
// This structure is part of the video output thread descriptor. * This structure is part of the video output thread descriptor.
// It describes the freetype specific properties of an output thread. * It describes the freetype specific properties of an output thread.
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
struct filter_sys_t struct filter_sys_t
{ {
char *psz_font_name; char *psz_font_name;
...@@ -181,24 +181,24 @@ struct filter_sys_t ...@@ -181,24 +181,24 @@ struct filter_sys_t
#endif #endif
}; };
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// Create: allocates osd-text video thread output method * Create: allocates osd-text video thread output method
////////////////////////////////////////////////////////////////////////////// *****************************************************************************
// This function allocates and initializes a Clone vout method. * This function allocates and initializes a Clone vout method.
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
static int Create( vlc_object_t *p_this ) static int Create(vlc_object_t *p_this)
{ {
filter_t *p_filter = (filter_t *)p_this; filter_t *p_filter = (filter_t *)p_this;
filter_sys_t *p_sys; filter_sys_t *p_sys;
// Allocate structure // Allocate structure
p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); p_filter->p_sys = p_sys = malloc(sizeof(filter_sys_t));
if( !p_sys ) if (!p_sys)
return VLC_ENOMEM; return VLC_ENOMEM;
p_sys->psz_font_name = var_CreateGetString( p_this, "quartztext-font" ); p_sys->psz_font_name = var_CreateGetString(p_this, "quartztext-font");
p_sys->i_font_opacity = 255; p_sys->i_font_opacity = 255;
p_sys->i_font_color = VLC_CLIP( var_CreateGetInteger( p_this, "quartztext-color" ) , 0, 0xFFFFFF ); p_sys->i_font_color = VLC_CLIP(var_CreateGetInteger(p_this, "quartztext-color") , 0, 0xFFFFFF);
p_sys->i_font_size = GetFontSize( p_filter ); p_sys->i_font_size = GetFontSize(p_filter);
p_filter->pf_render_text = RenderText; p_filter->pf_render_text = RenderText;
p_filter->pf_render_html = RenderHtml; p_filter->pf_render_html = RenderHtml;
...@@ -208,42 +208,37 @@ static int Create( vlc_object_t *p_this ) ...@@ -208,42 +208,37 @@ static int Create( vlc_object_t *p_this )
p_sys->i_fonts = 0; p_sys->i_fonts = 0;
#endif #endif
LoadFontsFromAttachments( p_filter ); LoadFontsFromAttachments(p_filter);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// Destroy: destroy Clone video thread output method * Destroy: destroy Clone video thread output method
////////////////////////////////////////////////////////////////////////////// *****************************************************************************
// Clean up all data and library connections * Clean up all data and library connections
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
static void Destroy( vlc_object_t *p_this ) static void Destroy(vlc_object_t *p_this)
{ {
filter_t *p_filter = (filter_t *)p_this; filter_t *p_filter = (filter_t *)p_this;
filter_sys_t *p_sys = p_filter->p_sys; filter_sys_t *p_sys = p_filter->p_sys;
#ifndef TARGET_OS_IPHONE #ifndef TARGET_OS_IPHONE
if( p_sys->p_fonts ) if (p_sys->p_fonts) {
{ for (int k = 0; k < p_sys->i_fonts; k++) {
int k; ATSFontDeactivate(p_sys->p_fonts[k], NULL, kATSOptionFlagsDefault);
for( k = 0; k < p_sys->i_fonts; k++ ) free(p_sys->p_fonts);
{
ATSFontDeactivate( p_sys->p_fonts[k], NULL, kATSOptionFlagsDefault );
}
free( p_sys->p_fonts );
} }
#endif #endif
free( p_sys->psz_font_name ); free(p_sys->psz_font_name);
free( p_sys ); free(p_sys);
} }
////////////////////////////////////////////////////////////////////////////// /*****************************************************************************
// Make any TTF/OTF fonts present in the attachments of the media file * Make any TTF/OTF fonts present in the attachments of the media file
// available to the Quartz engine for text rendering * available to the Quartz engine for text rendering
////////////////////////////////////////////////////////////////////////////// *****************************************************************************/
static int LoadFontsFromAttachments( filter_t *p_filter ) static int LoadFontsFromAttachments(filter_t *p_filter)
{ {
#ifdef TARGET_OS_IPHONE #ifdef TARGET_OS_IPHONE
VLC_UNUSED(p_filter); VLC_UNUSED(p_filter);
...@@ -253,65 +248,58 @@ static int LoadFontsFromAttachments( filter_t *p_filter ) ...@@ -253,65 +248,58 @@ static int LoadFontsFromAttachments( filter_t *p_filter )
input_attachment_t **pp_attachments; input_attachment_t **pp_attachments;
int i_attachments_cnt; int i_attachments_cnt;
if( filter_GetInputAttachments( p_filter, &pp_attachments, &i_attachments_cnt ) ) if (filter_GetInputAttachments(p_filter, &pp_attachments, &i_attachments_cnt))
return VLC_EGENERIC; return VLC_EGENERIC;
p_sys->i_fonts = 0; p_sys->i_fonts = 0;
p_sys->p_fonts = malloc( i_attachments_cnt * sizeof( ATSFontContainerRef ) ); p_sys->p_fonts = malloc(i_attachments_cnt * sizeof(ATSFontContainerRef));
if(! p_sys->p_fonts ) if (! p_sys->p_fonts)
return VLC_ENOMEM; return VLC_ENOMEM;
for( int k = 0; k < i_attachments_cnt; k++ ) for (int k = 0; k < i_attachments_cnt; k++) {
{
input_attachment_t *p_attach = pp_attachments[k]; input_attachment_t *p_attach = pp_attachments[k];
if( ( !strcmp( p_attach->psz_mime, "application/x-truetype-font" ) || // TTF if ((!strcmp(p_attach->psz_mime, "application/x-truetype-font") || // TTF
!strcmp( p_attach->psz_mime, "application/x-font-otf" ) ) && // OTF !strcmp(p_attach->psz_mime, "application/x-font-otf")) && // OTF
p_attach->i_data > 0 && p_attach->p_data ) p_attach->i_data > 0 && p_attach->p_data) {
{
ATSFontContainerRef container; ATSFontContainerRef container;
if( noErr == ATSFontActivateFromMemory( p_attach->p_data, if (noErr == ATSFontActivateFromMemory(p_attach->p_data,
p_attach->i_data, p_attach->i_data,
kATSFontContextLocal, kATSFontContextLocal,
kATSFontFormatUnspecified, kATSFontFormatUnspecified,
NULL, NULL,
kATSOptionFlagsDefault, kATSOptionFlagsDefault,
&container )) &container))
{
p_sys->p_fonts[ p_sys->i_fonts++ ] = container; p_sys->p_fonts[ p_sys->i_fonts++ ] = container;
}
} }
vlc_input_attachment_Delete( p_attach ); vlc_input_attachment_Delete(p_attach);
} }
free( pp_attachments ); free(pp_attachments);
return VLC_SUCCESS; return VLC_SUCCESS;
#endif #endif
} }
static char *EliminateCRLF( char *psz_string ) static char *EliminateCRLF(char *psz_string)
{ {
char *p;
char *q; char *q;
for( p = psz_string; p && *p; p++ ) for (char * p = psz_string; p && *p; p++) {
{ if ((*p == '\r') && (*(p+1) == '\n')) {
if( ( *p == '\r' ) && ( *(p+1) == '\n' ) ) for (q = p + 1; *q; q++)
{ *(q - 1) = *q;
for( q = p + 1; *q; q++ )
*( q - 1 ) = *q;
*( q - 1 ) = '\0'; *(q - 1) = '\0';
} }
} }
return psz_string; return psz_string;
} }
// Renders a text subpicture region into another one. /* Renders a text subpicture region into another one.
// It is used as pf_add_string callback in the vout method by this module * 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, static int RenderText(filter_t *p_filter, subpicture_region_t *p_region_out,
subpicture_region_t *p_region_in, subpicture_region_t *p_region_in,
const vlc_fourcc_t *p_chroma_list ) const vlc_fourcc_t *p_chroma_list)
{ {
filter_sys_t *p_sys = p_filter->p_sys; filter_sys_t *p_sys = p_filter->p_sys;
char *psz_string; char *psz_string;
...@@ -321,41 +309,40 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, ...@@ -321,41 +309,40 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
vlc_value_t val; vlc_value_t val;
b_bold = b_uline = b_italic = FALSE; b_bold = b_uline = b_italic = FALSE;
p_sys->i_font_size = GetFontSize( p_filter ); p_sys->i_font_size = GetFontSize(p_filter);
// Sanity check // Sanity check
if( !p_region_in || !p_region_out ) return VLC_EGENERIC; if (!p_region_in || !p_region_out)
return VLC_EGENERIC;
psz_string = p_region_in->psz_text; psz_string = p_region_in->psz_text;
if( !psz_string || !*psz_string ) return VLC_EGENERIC; if (!psz_string || !*psz_string)
return VLC_EGENERIC;
if( p_region_in->p_style )
{ if (p_region_in->p_style) {
i_font_color = VLC_CLIP( p_region_in->p_style->i_font_color, 0, 0xFFFFFF ); i_font_color = VLC_CLIP(p_region_in->p_style->i_font_color, 0, 0xFFFFFF);
i_font_alpha = VLC_CLIP( p_region_in->p_style->i_font_alpha, 0, 255 ); i_font_alpha = VLC_CLIP(p_region_in->p_style->i_font_alpha, 0, 255);
i_font_size = VLC_CLIP( p_region_in->p_style->i_font_size, 0, 255 ); i_font_size = VLC_CLIP(p_region_in->p_style->i_font_size, 0, 255);
if( p_region_in->p_style->i_style_flags ) if (p_region_in->p_style->i_style_flags) {
{ if (p_region_in->p_style->i_style_flags & STYLE_BOLD)
if( p_region_in->p_style->i_style_flags & STYLE_BOLD )
b_bold = TRUE; b_bold = TRUE;
if( p_region_in->p_style->i_style_flags & STYLE_ITALIC ) if (p_region_in->p_style->i_style_flags & STYLE_ITALIC)
b_italic = TRUE; b_italic = TRUE;
if( p_region_in->p_style->i_style_flags & STYLE_UNDERLINE ) if (p_region_in->p_style->i_style_flags & STYLE_UNDERLINE)
b_uline = TRUE; b_uline = TRUE;
} }
} } else {
else
{
i_font_color = p_sys->i_font_color; i_font_color = p_sys->i_font_color;
i_font_alpha = 255 - p_sys->i_font_opacity; i_font_alpha = 255 - p_sys->i_font_opacity;
i_font_size = p_sys->i_font_size; i_font_size = p_sys->i_font_size;
} }
if( !i_font_alpha ) i_font_alpha = 255 - p_sys->i_font_opacity; if (!i_font_alpha)
i_font_alpha = 255 - p_sys->i_font_opacity;
if( i_font_size <= 0 ) if (i_font_size <= 0) {
{ msg_Warn(p_filter, "invalid fontsize, using 12");
msg_Warn( p_filter, "invalid fontsize, using 12" ); if (VLC_SUCCESS == var_Get(p_filter, "scale", &val))
if( VLC_SUCCESS == var_Get( p_filter, "scale", &val ))
i_font_size = 12 * val.i_int / 1000; i_font_size = 12 * val.i_int / 1000;
else else
i_font_size = 12; i_font_size = 12;
...@@ -366,61 +353,55 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out, ...@@ -366,61 +353,55 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
CFMutableAttributedStringRef p_attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFMutableAttributedStringRef p_attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
if( p_attrString ) if (p_attrString) {
{
CFStringRef p_cfString; CFStringRef p_cfString;
int len; int len;
EliminateCRLF( psz_string); EliminateCRLF(psz_string);
p_cfString = CFStringCreateWithCString( NULL, psz_string, kCFStringEncodingUTF8 ); p_cfString = CFStringCreateWithCString(NULL, psz_string, kCFStringEncodingUTF8);
CFAttributedStringReplaceString( p_attrString, CFRangeMake(0, 0), p_cfString ); CFAttributedStringReplaceString(p_attrString, CFRangeMake(0, 0), p_cfString);
CFRelease( p_cfString ); CFRelease(p_cfString);
len = CFAttributedStringGetLength( p_attrString ); len = CFAttributedStringGetLength(p_attrString);
setFontAttibutes( p_sys->psz_font_name, i_font_size, i_font_color, b_bold, b_italic, b_uline, setFontAttibutes(p_sys->psz_font_name, i_font_size, i_font_color, b_bold, b_italic, b_uline,
CFRangeMake( 0, len ), p_attrString); CFRangeMake(0, len), p_attrString);
RenderYUVA( p_filter, p_region_out, p_attrString ); RenderYUVA(p_filter, p_region_out, p_attrString);
CFRelease( p_attrString ); CFRelease(p_attrString);
} }
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, static int PushFont(font_stack_t **p_font, const char *psz_name, int i_size,
uint32_t i_color ) uint32_t i_color)
{ {
font_stack_t *p_new; font_stack_t *p_new;
if( !p_font ) if (!p_font)
return VLC_EGENERIC; return VLC_EGENERIC;
p_new = malloc( sizeof( font_stack_t ) ); p_new = malloc(sizeof(font_stack_t));
if( ! p_new ) if (! p_new)
return VLC_ENOMEM; return VLC_ENOMEM;
p_new->p_next = NULL; p_new->p_next = NULL;
if( psz_name ) if (psz_name)
p_new->psz_name = strdup( psz_name ); p_new->psz_name = strdup(psz_name);
else else
p_new->psz_name = NULL; p_new->psz_name = NULL;
p_new->i_size = i_size; p_new->i_size = i_size;
p_new->i_color = i_color; p_new->i_color = i_color;
if( !*p_font ) if (!*p_font)
{
*p_font = p_new; *p_font = p_new;
} else {
else
{
font_stack_t *p_last; font_stack_t *p_last;
for( p_last = *p_font; for (p_last = *p_font; p_last->p_next; p_last = p_last->p_next)
p_last->p_next;
p_last = p_last->p_next )
; ;
p_last->p_next = p_new; p_last->p_next = p_new;
...@@ -428,43 +409,39 @@ static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, ...@@ -428,43 +409,39 @@ static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int PopFont( font_stack_t **p_font ) static int PopFont(font_stack_t **p_font)
{ {
font_stack_t *p_last, *p_next_to_last; font_stack_t *p_last, *p_next_to_last;
if( !p_font || !*p_font ) if (!p_font || !*p_font)
return VLC_EGENERIC; return VLC_EGENERIC;
p_next_to_last = NULL; p_next_to_last = NULL;
for( p_last = *p_font; for (p_last = *p_font; p_last->p_next; p_last = p_last->p_next)
p_last->p_next;
p_last = p_last->p_next )
{
p_next_to_last = p_last; p_next_to_last = p_last;
}
if( p_next_to_last ) if (p_next_to_last)
p_next_to_last->p_next = NULL; p_next_to_last->p_next = NULL;
else else
*p_font = NULL; *p_font = NULL;
free( p_last->psz_name ); free(p_last->psz_name);
free( p_last ); free(p_last);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size, static int PeekFont(font_stack_t **p_font, char **psz_name, int *i_size,
uint32_t *i_color ) uint32_t *i_color)
{ {
font_stack_t *p_last; font_stack_t *p_last;
if( !p_font || !*p_font ) if (!p_font || !*p_font)
return VLC_EGENERIC; return VLC_EGENERIC;
for( p_last=*p_font; for (p_last=*p_font;
p_last->p_next; p_last->p_next;
p_last=p_last->p_next ) p_last=p_last->p_next)
; ;
*psz_name = p_last->psz_name; *psz_name = p_last->psz_name;
...@@ -474,8 +451,8 @@ static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size, ...@@ -474,8 +451,8 @@ static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int HandleFontAttributes( xml_reader_t *p_xml_reader, static int HandleFontAttributes(xml_reader_t *p_xml_reader,
font_stack_t **p_fonts ) font_stack_t **p_fonts)
{ {
int rv; int rv;
char *psz_fontname = NULL; char *psz_fontname = NULL;
...@@ -484,167 +461,156 @@ static int HandleFontAttributes( xml_reader_t *p_xml_reader, ...@@ -484,167 +461,156 @@ static int HandleFontAttributes( xml_reader_t *p_xml_reader,
int i_font_size = 24; int i_font_size = 24;
const char *attr, *value; const char *attr, *value;
// Default all attributes to the top font in the stack -- in case not /* Default all attributes to the top font in the stack -- in case not
// all attributes are specified in the sub-font * all attributes are specified in the sub-font */
if( VLC_SUCCESS == PeekFont( p_fonts, if (VLC_SUCCESS == PeekFont(p_fonts,
&psz_fontname, &psz_fontname,
&i_font_size, &i_font_size,
&i_font_color )) &i_font_color)) {
{ psz_fontname = strdup(psz_fontname);
psz_fontname = strdup( psz_fontname );
i_font_size = i_font_size; i_font_size = i_font_size;
} }
i_font_alpha = (i_font_color >> 24) & 0xff; i_font_alpha = (i_font_color >> 24) & 0xff;
i_font_color &= 0x00ffffff; i_font_color &= 0x00ffffff;
while ( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) while ((attr = xml_ReaderNextAttr(p_xml_reader, &value))) {
{ if (!strcasecmp("face", attr)) {
if( !strcasecmp( "face", attr ) ) free(psz_fontname);
{ psz_fontname = strdup(value);
free( psz_fontname ); } else if (!strcasecmp("size", attr)) {
psz_fontname = strdup( value ); if ((*value == '+') || (*value == '-')) {
} int i_value = atoi(value);
else if( !strcasecmp( "size", attr ) )
{ if ((i_value >= -5) && (i_value <= 5))
if( ( *value == '+' ) || ( *value == '-' ) ) i_font_size += (i_value * i_font_size) / 10;
{ else if (i_value < -5)
int i_value = atoi( 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; i_font_size = - i_value;
else if( i_value > 5 ) else if (i_value > 5)
i_font_size = i_value; i_font_size = i_value;
} }
else else
i_font_size = atoi( value ); i_font_size = atoi(value);
} } else if (!strcasecmp("color", attr) && (value[0] == '#')) {
else if( !strcasecmp( "color", attr ) && ( value[0] == '#' ) ) i_font_color = strtol(value + 1, NULL, 16);
{
i_font_color = strtol( value + 1, NULL, 16 );
i_font_color &= 0x00ffffff; i_font_color &= 0x00ffffff;
} } else if (!strcasecmp("alpha", attr) && (value[0] == '#')) {
else if( !strcasecmp( "alpha", attr ) && ( value[0] == '#' ) ) i_font_alpha = strtol(value + 1, NULL, 16);
{
i_font_alpha = strtol( value + 1, NULL, 16 );
i_font_alpha &= 0xff; i_font_alpha &= 0xff;
} }
} }
rv = PushFont( p_fonts, rv = PushFont(p_fonts,
psz_fontname, psz_fontname,
i_font_size, i_font_size,
(i_font_color & 0xffffff) | ((i_font_alpha & 0xff) << 24) ); (i_font_color & 0xffffff) | ((i_font_alpha & 0xff) << 24));
free( psz_fontname ); free(psz_fontname);
return rv; return rv;
} }
static void setFontAttibutes( char *psz_fontname, int i_font_size, uint32_t i_font_color, static void setFontAttibutes(char *psz_fontname, int i_font_size, uint32_t i_font_color,
bool b_bold, bool b_italic, bool b_underline, bool b_bold, bool b_italic, bool b_underline,
CFRange p_range, CFMutableAttributedStringRef p_attrString ) CFRange p_range, CFMutableAttributedStringRef p_attrString)
{ {
CFStringRef p_cfString; CFStringRef p_cfString;
CTFontRef p_font; CTFontRef p_font;
// Handle font name and size // Handle font name and size
p_cfString = CFStringCreateWithCString( NULL, p_cfString = CFStringCreateWithCString(NULL,
psz_fontname, psz_fontname,
kCFStringEncodingUTF8 ); kCFStringEncodingUTF8);
p_font = CTFontCreateWithName( p_cfString, p_font = CTFontCreateWithName(p_cfString,
(float)i_font_size, (float)i_font_size,
NULL ); NULL);
CFRelease( p_cfString ); CFRelease(p_cfString);
CFAttributedStringSetAttribute( p_attrString, CFAttributedStringSetAttribute(p_attrString,
p_range, p_range,
kCTFontAttributeName, kCTFontAttributeName,
p_font ); p_font);
CFRelease( p_font ); CFRelease(p_font);
// Handle Underline // Handle Underline
SInt32 _uline; SInt32 _uline;
if( b_underline ) if (b_underline)
_uline = kCTUnderlineStyleSingle; _uline = kCTUnderlineStyleSingle;
else else
_uline = kCTUnderlineStyleNone; _uline = kCTUnderlineStyleNone;
CFNumberRef underline = CFNumberCreate(NULL, kCFNumberSInt32Type, &_uline); CFNumberRef underline = CFNumberCreate(NULL, kCFNumberSInt32Type, &_uline);
CFAttributedStringSetAttribute( p_attrString, CFAttributedStringSetAttribute(p_attrString,
p_range, p_range,
kCTUnderlineStyleAttributeName, kCTUnderlineStyleAttributeName,
underline ); underline);
CFRelease( underline ); CFRelease(underline);
// Handle Bold // Handle Bold
float _weight; float _weight;
if( b_bold ) if (b_bold)
_weight = 0.5; _weight = 0.5;
else else
_weight = 0.0; _weight = 0.0;
CFNumberRef weight = CFNumberCreate(NULL, kCFNumberFloatType, &_weight); CFNumberRef weight = CFNumberCreate(NULL, kCFNumberFloatType, &_weight);
CFAttributedStringSetAttribute( p_attrString, CFAttributedStringSetAttribute(p_attrString,
p_range, p_range,
kCTFontWeightTrait, kCTFontWeightTrait,
weight ); weight);
CFRelease( weight ); CFRelease(weight);
// Handle Italic // Handle Italic
float _slant; float _slant;
if( b_italic ) if (b_italic)
_slant = 1.0; _slant = 1.0;
else else
_slant = 0.0; _slant = 0.0;
CFNumberRef slant = CFNumberCreate(NULL, kCFNumberFloatType, &_slant); CFNumberRef slant = CFNumberCreate(NULL, kCFNumberFloatType, &_slant);
CFAttributedStringSetAttribute( p_attrString, CFAttributedStringSetAttribute(p_attrString,
p_range, p_range,
kCTFontSlantTrait, kCTFontSlantTrait,
slant ); slant);
CFRelease( slant ); CFRelease(slant);
// Handle foreground colour // Handle foreground colour
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = { (float)((i_font_color & 0x00ff0000) >> 16) / 255.0, CGFloat components[] = { (float)((i_font_color & 0x00ff0000) >> 16) / 255.0,
(float)((i_font_color & 0x0000ff00) >> 8) / 255.0, (float)((i_font_color & 0x0000ff00) >> 8) / 255.0,
(float)((i_font_color & 0x000000ff) ) / 255.0, (float)((i_font_color & 0x000000ff)) / 255.0,
(float)(255-((i_font_color & 0xff000000) >> 24)) / 255.0 }; (float)(255-((i_font_color & 0xff000000) >> 24)) / 255.0 };
CGColorRef fg_text = CGColorCreate(rgbColorSpace, components); CGColorRef fg_text = CGColorCreate(rgbColorSpace, components);
CGColorSpaceRelease(rgbColorSpace); CGColorSpaceRelease(rgbColorSpace);
CFAttributedStringSetAttribute( p_attrString, CFAttributedStringSetAttribute(p_attrString,
p_range, p_range,
kCTForegroundColorAttributeName, kCTForegroundColorAttributeName,
fg_text ); fg_text);
CFRelease( fg_text ); CFRelease(fg_text);
} }
static void GetAttrStrFromFontStack( font_stack_t **p_fonts, static void GetAttrStrFromFontStack(font_stack_t **p_fonts,
bool b_bold, bool b_italic, bool b_uline, bool b_bold, bool b_italic, bool b_uline,
CFRange p_range, CFMutableAttributedStringRef p_attrString ) CFRange p_range, CFMutableAttributedStringRef p_attrString)
{ {
char *psz_fontname = NULL; char *psz_fontname = NULL;
int i_font_size = 0; int i_font_size = 0;
uint32_t i_font_color = 0; uint32_t i_font_color = 0;
if( VLC_SUCCESS == PeekFont( p_fonts, &psz_fontname, &i_font_size, if (VLC_SUCCESS == PeekFont(p_fonts, &psz_fontname, &i_font_size,
&i_font_color )) &i_font_color)) {
{ setFontAttibutes(psz_fontname,
setFontAttibutes( psz_fontname, i_font_size,
i_font_size, i_font_color,
i_font_color, b_bold, b_italic, b_uline,
b_bold, b_italic, b_uline, p_range,
p_range, p_attrString);
p_attrString );
} }
} }
static int ProcessNodes( filter_t *p_filter, static int ProcessNodes(filter_t *p_filter,
xml_reader_t *p_xml_reader, xml_reader_t *p_xml_reader,
text_style_t *p_font_style, text_style_t *p_font_style,
CFMutableAttributedStringRef p_attrString ) CFMutableAttributedStringRef p_attrString)
{ {
int rv = VLC_SUCCESS; int rv = VLC_SUCCESS;
filter_sys_t *p_sys = p_filter->p_sys; filter_sys_t *p_sys = p_filter->p_sys;
...@@ -657,67 +623,61 @@ static int ProcessNodes( filter_t *p_filter, ...@@ -657,67 +623,61 @@ static int ProcessNodes( filter_t *p_filter,
bool b_bold = false; bool b_bold = false;
bool b_uline = false; bool b_uline = false;
if( p_font_style ) if (p_font_style) {
{ rv = PushFont(&p_fonts,
rv = PushFont( &p_fonts,
p_font_style->psz_fontname, p_font_style->psz_fontname,
p_font_style->i_font_size, p_font_style->i_font_size,
(p_font_style->i_font_color & 0xffffff) | (p_font_style->i_font_color & 0xffffff) |
((p_font_style->i_font_alpha & 0xff) << 24) ); ((p_font_style->i_font_alpha & 0xff) << 24));
if( p_font_style->i_style_flags & STYLE_BOLD ) if (p_font_style->i_style_flags & STYLE_BOLD)
b_bold = true; b_bold = true;
if( p_font_style->i_style_flags & STYLE_ITALIC ) if (p_font_style->i_style_flags & STYLE_ITALIC)
b_italic = true; b_italic = true;
if( p_font_style->i_style_flags & STYLE_UNDERLINE ) if (p_font_style->i_style_flags & STYLE_UNDERLINE)
b_uline = true; b_uline = true;
} } else {
else rv = PushFont(&p_fonts,
{
rv = PushFont( &p_fonts,
p_sys->psz_font_name, p_sys->psz_font_name,
p_sys->i_font_size, p_sys->i_font_size,
p_sys->i_font_color ); p_sys->i_font_color);
} }
if( rv != VLC_SUCCESS ) if (rv != VLC_SUCCESS)
return rv; return rv;
while ( ( type = xml_ReaderNextNode( p_xml_reader, &node ) ) > 0 ) while ((type = xml_ReaderNextNode(p_xml_reader, &node)) > 0) {
{ switch (type) {
switch ( type )
{
case XML_READER_ENDELEM: case XML_READER_ENDELEM:
if( !strcasecmp( "font", node ) ) if (!strcasecmp("font", node))
PopFont( &p_fonts ); PopFont(&p_fonts);
else if( !strcasecmp( "b", node ) ) else if (!strcasecmp("b", node))
b_bold = false; b_bold = false;
else if( !strcasecmp( "i", node ) ) else if (!strcasecmp("i", node))
b_italic = false; b_italic = false;
else if( !strcasecmp( "u", node ) ) else if (!strcasecmp("u", node))
b_uline = false; b_uline = false;
break; break;
case XML_READER_STARTELEM: case XML_READER_STARTELEM:
if( !strcasecmp( "font", node ) ) if (!strcasecmp("font", node))
rv = HandleFontAttributes( p_xml_reader, &p_fonts ); rv = HandleFontAttributes(p_xml_reader, &p_fonts);
else if( !strcasecmp( "b", node ) ) else if (!strcasecmp("b", node))
b_bold = true; b_bold = true;
else if( !strcasecmp( "i", node ) ) else if (!strcasecmp("i", node))
b_italic = true; b_italic = true;
else if( !strcasecmp( "u", node ) ) else if (!strcasecmp("u", node))
b_uline = true; b_uline = true;
else if( !strcasecmp( "br", node ) ) else if (!strcasecmp("br", node)) {
{
CFMutableAttributedStringRef p_attrnode = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFMutableAttributedStringRef p_attrnode = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString( p_attrnode, CFRangeMake(0, 0), CFSTR("\n") ); CFAttributedStringReplaceString(p_attrnode, CFRangeMake(0, 0), CFSTR("\n"));
GetAttrStrFromFontStack( &p_fonts, b_bold, b_italic, b_uline, GetAttrStrFromFontStack(&p_fonts, b_bold, b_italic, b_uline,
CFRangeMake( 0, 1 ), CFRangeMake(0, 1),
p_attrnode ); p_attrnode);
CFAttributedStringReplaceAttributedString( p_attrString, CFAttributedStringReplaceAttributedString(p_attrString,
CFRangeMake(CFAttributedStringGetLength(p_attrString), 0), CFRangeMake(CFAttributedStringGetLength(p_attrString), 0),
p_attrnode); p_attrnode);
CFRelease( p_attrnode ); CFRelease(p_attrnode);
} }
break; break;
case XML_READER_TEXT: case XML_READER_TEXT:
...@@ -726,176 +686,157 @@ static int ProcessNodes( filter_t *p_filter, ...@@ -726,176 +686,157 @@ static int ProcessNodes( filter_t *p_filter,
int len; int len;
// Turn any multiple-whitespaces into single spaces // Turn any multiple-whitespaces into single spaces
char *dup = strdup( node ); char *dup = strdup(node);
if( !dup ) if (!dup)
break; break;
char *s = strpbrk( dup, "\t\r\n " ); char *s = strpbrk(dup, "\t\r\n ");
while( s ) while(s)
{ {
int i_whitespace = strspn( s, "\t\r\n " ); int i_whitespace = strspn(s, "\t\r\n ");
if( i_whitespace > 1 ) if (i_whitespace > 1)
memmove( &s[1], memmove(&s[1],
&s[i_whitespace], &s[i_whitespace],
strlen( s ) - i_whitespace + 1 ); strlen(s) - i_whitespace + 1);
*s++ = ' '; *s++ = ' ';
s = strpbrk( s, "\t\r\n " ); s = strpbrk(s, "\t\r\n ");
} }
CFMutableAttributedStringRef p_attrnode = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFMutableAttributedStringRef p_attrnode = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
p_cfString = CFStringCreateWithCString( NULL, dup, kCFStringEncodingUTF8 ); p_cfString = CFStringCreateWithCString(NULL, dup, kCFStringEncodingUTF8);
CFAttributedStringReplaceString( p_attrnode, CFRangeMake(0, 0), p_cfString ); CFAttributedStringReplaceString(p_attrnode, CFRangeMake(0, 0), p_cfString);
CFRelease( p_cfString ); CFRelease(p_cfString);
len = CFAttributedStringGetLength( p_attrnode ); len = CFAttributedStringGetLength(p_attrnode);
GetAttrStrFromFontStack( &p_fonts, b_bold, b_italic, b_uline, GetAttrStrFromFontStack(&p_fonts, b_bold, b_italic, b_uline,
CFRangeMake( 0, len ), CFRangeMake(0, len),
p_attrnode ); p_attrnode);
CFAttributedStringReplaceAttributedString( p_attrString, CFAttributedStringReplaceAttributedString(p_attrString,
CFRangeMake(CFAttributedStringGetLength(p_attrString), 0), CFRangeMake(CFAttributedStringGetLength(p_attrString), 0),
p_attrnode); p_attrnode);
CFRelease( p_attrnode ); CFRelease(p_attrnode);
free( dup ); free(dup);
break; break;
} }
} }
} }
while( VLC_SUCCESS == PopFont( &p_fonts ) ); while(VLC_SUCCESS == PopFont(&p_fonts));
return rv; return rv;
} }
static int RenderHtml( filter_t *p_filter, subpicture_region_t *p_region_out, static int RenderHtml(filter_t *p_filter, subpicture_region_t *p_region_out,
subpicture_region_t *p_region_in, subpicture_region_t *p_region_in,
const vlc_fourcc_t *p_chroma_list ) const vlc_fourcc_t *p_chroma_list)
{ {
int rv = VLC_SUCCESS; int rv = VLC_SUCCESS;
stream_t *p_sub = NULL; stream_t *p_sub = NULL;
xml_t *p_xml = NULL; xml_t *p_xml = NULL;
xml_reader_t *p_xml_reader = NULL; xml_reader_t *p_xml_reader = NULL;
if( !p_region_in || !p_region_in->psz_html ) if (!p_region_in || !p_region_in->psz_html)
return VLC_EGENERIC; return VLC_EGENERIC;
/* Reset the default fontsize in case screen metrics have changed */ /* Reset the default fontsize in case screen metrics have changed */
p_filter->p_sys->i_font_size = GetFontSize( p_filter ); p_filter->p_sys->i_font_size = GetFontSize(p_filter);
p_sub = stream_MemoryNew( VLC_OBJECT(p_filter), p_sub = stream_MemoryNew(VLC_OBJECT(p_filter),
(uint8_t *) p_region_in->psz_html, (uint8_t *) p_region_in->psz_html,
strlen( p_region_in->psz_html ), strlen(p_region_in->psz_html),
true ); true);
if( p_sub ) if (p_sub) {
{ p_xml = xml_Create(p_filter);
p_xml = xml_Create( p_filter ); if (p_xml) {
if( p_xml )
{
bool b_karaoke = false; bool b_karaoke = false;
p_xml_reader = xml_ReaderCreate( p_xml, p_sub ); p_xml_reader = xml_ReaderCreate(p_xml, p_sub);
if( p_xml_reader ) if (p_xml_reader) {
{
/* Look for Root Node */ /* Look for Root Node */
const char *name; const char *name;
if( xml_ReaderNextNode( p_xml_reader, &name ) if (xml_ReaderNextNode(p_xml_reader, &name)
== XML_READER_STARTELEM ) == XML_READER_STARTELEM) {
{ if (!strcasecmp("karaoke", name)) {
if( !strcasecmp( "karaoke", name ) )
{
/* We're going to have to render the text a number /* We're going to have to render the text a number
* of times to show the progress marker on the text. * of times to show the progress marker on the text.
*/ */
var_SetBool( p_filter, "text-rerender", true ); var_SetBool(p_filter, "text-rerender", true);
b_karaoke = true; b_karaoke = true;
} } else if (!strcasecmp("text", name))
else if( !strcasecmp( "text", name ) )
{
b_karaoke = false; b_karaoke = false;
} else {
else
{
/* Only text and karaoke tags are supported */ /* Only text and karaoke tags are supported */
msg_Dbg( p_filter, "Unsupported top-level tag " msg_Dbg(p_filter, "Unsupported top-level tag "
"<%s> ignored.", name ); "<%s> ignored.", name);
rv = VLC_EGENERIC; rv = VLC_EGENERIC;
} }
} } else {
else msg_Err(p_filter, "Malformed HTML subtitle");
{
msg_Err( p_filter, "Malformed HTML subtitle" );
rv = VLC_EGENERIC; rv = VLC_EGENERIC;
} }
if( rv != VLC_SUCCESS ) if (rv != VLC_SUCCESS) {
{ xml_ReaderDelete(p_xml_reader);
xml_ReaderDelete( p_xml_reader );
p_xml_reader = NULL; p_xml_reader = NULL;
} }
} }
if( p_xml_reader ) if (p_xml_reader) {
{
int i_len; int i_len;
CFMutableAttributedStringRef p_attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFMutableAttributedStringRef p_attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
rv = ProcessNodes( p_filter, p_xml_reader, rv = ProcessNodes(p_filter, p_xml_reader,
p_region_in->p_style, p_attrString ); p_region_in->p_style, p_attrString);
i_len = CFAttributedStringGetLength( p_attrString ); i_len = CFAttributedStringGetLength(p_attrString);
p_region_out->i_x = p_region_in->i_x; p_region_out->i_x = p_region_in->i_x;
p_region_out->i_y = p_region_in->i_y; p_region_out->i_y = p_region_in->i_y;
if(( rv == VLC_SUCCESS ) && ( i_len > 0 )) if ((rv == VLC_SUCCESS) && (i_len > 0))
{ RenderYUVA(p_filter, p_region_out, p_attrString);
RenderYUVA( p_filter, p_region_out, p_attrString );
}
CFRelease(p_attrString); CFRelease(p_attrString);
xml_ReaderDelete( p_xml_reader ); xml_ReaderDelete(p_xml_reader);
} }
xml_Delete( p_xml ); xml_Delete(p_xml);
} }
stream_Delete( p_sub ); stream_Delete(p_sub);
} }
return rv; return rv;
} }
static CGContextRef CreateOffScreenContext( int i_width, int i_height, static CGContextRef CreateOffScreenContext(int i_width, int i_height,
offscreen_bitmap_t **pp_memory, CGColorSpaceRef *pp_colorSpace ) offscreen_bitmap_t **pp_memory, CGColorSpaceRef *pp_colorSpace)
{ {
offscreen_bitmap_t *p_bitmap; offscreen_bitmap_t *p_bitmap;
CGContextRef p_context = NULL; CGContextRef p_context = NULL;
p_bitmap = (offscreen_bitmap_t *) malloc( sizeof( offscreen_bitmap_t )); p_bitmap = (offscreen_bitmap_t *) malloc(sizeof(offscreen_bitmap_t));
if( p_bitmap ) if (p_bitmap) {
{
p_bitmap->i_bitsPerChannel = 8; p_bitmap->i_bitsPerChannel = 8;
p_bitmap->i_bitsPerPixel = 4 * p_bitmap->i_bitsPerChannel; // A,R,G,B p_bitmap->i_bitsPerPixel = 4 * p_bitmap->i_bitsPerChannel; // A,R,G,B
p_bitmap->i_bytesPerPixel = p_bitmap->i_bitsPerPixel / 8; p_bitmap->i_bytesPerPixel = p_bitmap->i_bitsPerPixel / 8;
p_bitmap->i_bytesPerRow = i_width * p_bitmap->i_bytesPerPixel; p_bitmap->i_bytesPerRow = i_width * p_bitmap->i_bytesPerPixel;
p_bitmap->p_data = calloc( i_height, p_bitmap->i_bytesPerRow ); p_bitmap->p_data = calloc(i_height, p_bitmap->i_bytesPerRow);
*pp_colorSpace = CGColorSpaceCreateDeviceRGB(); *pp_colorSpace = CGColorSpaceCreateDeviceRGB();
if( p_bitmap->p_data && *pp_colorSpace ) if (p_bitmap->p_data && *pp_colorSpace)
{ p_context = CGBitmapContextCreate(p_bitmap->p_data, i_width, i_height,
p_context = CGBitmapContextCreate( p_bitmap->p_data, i_width, i_height,
p_bitmap->i_bitsPerChannel, p_bitmap->i_bytesPerRow, p_bitmap->i_bitsPerChannel, p_bitmap->i_bytesPerRow,
*pp_colorSpace, kCGImageAlphaPremultipliedFirst); *pp_colorSpace, kCGImageAlphaPremultipliedFirst);
}
if( p_context ) if (p_context) {
{ if (CGContextSetAllowsAntialiasing != NULL)
if( CGContextSetAllowsAntialiasing != NULL ) CGContextSetAllowsAntialiasing(p_context, true);
{
CGContextSetAllowsAntialiasing( p_context, true );
}
} }
*pp_memory = p_bitmap; *pp_memory = p_bitmap;
} }
...@@ -903,43 +844,41 @@ static CGContextRef CreateOffScreenContext( int i_width, int i_height, ...@@ -903,43 +844,41 @@ static CGContextRef CreateOffScreenContext( int i_width, int i_height,
return p_context; return p_context;
} }
static offscreen_bitmap_t *Compose( int i_text_align, static offscreen_bitmap_t *Compose(int i_text_align,
CFMutableAttributedStringRef p_attrString, CFMutableAttributedStringRef p_attrString,
unsigned i_width, unsigned i_width,
unsigned i_height, unsigned i_height,
unsigned *pi_textblock_height ) unsigned *pi_textblock_height)
{ {
offscreen_bitmap_t *p_offScreen = NULL; offscreen_bitmap_t *p_offScreen = NULL;
CGColorSpaceRef p_colorSpace = NULL; CGColorSpaceRef p_colorSpace = NULL;
CGContextRef p_context = NULL; CGContextRef p_context = NULL;
p_context = CreateOffScreenContext( i_width, i_height, &p_offScreen, &p_colorSpace ); p_context = CreateOffScreenContext(i_width, i_height, &p_offScreen, &p_colorSpace);
*pi_textblock_height = 0; *pi_textblock_height = 0;
if( p_context ) if (p_context) {
{
float horiz_flush; float horiz_flush;
CGContextSetTextMatrix( p_context, CGAffineTransformIdentity ); CGContextSetTextMatrix(p_context, CGAffineTransformIdentity);
if( i_text_align == SUBPICTURE_ALIGN_RIGHT ) if (i_text_align == SUBPICTURE_ALIGN_RIGHT)
horiz_flush = 1.0; horiz_flush = 1.0;
else if( i_text_align != SUBPICTURE_ALIGN_LEFT ) else if (i_text_align != SUBPICTURE_ALIGN_LEFT)
horiz_flush = 0.5; horiz_flush = 0.5;
else else
horiz_flush = 0.0; horiz_flush = 0.0;
// Create the framesetter with the attributed string. // Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(p_attrString); CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(p_attrString);
if( framesetter ) if (framesetter) {
{
CTFrameRef frame; CTFrameRef frame;
CGMutablePathRef p_path = CGPathCreateMutable(); CGMutablePathRef p_path = CGPathCreateMutable();
CGRect p_bounds = CGRectMake( (float)HORIZONTAL_MARGIN, CGRect p_bounds = CGRectMake((float)HORIZONTAL_MARGIN,
(float)VERTICAL_MARGIN, (float)VERTICAL_MARGIN,
(float)(i_width - HORIZONTAL_MARGIN*2), (float)(i_width - HORIZONTAL_MARGIN*2),
(float)(i_height - VERTICAL_MARGIN *2)); (float)(i_height - VERTICAL_MARGIN *2));
CGPathAddRect( p_path, NULL, p_bounds ); CGPathAddRect(p_path, NULL, p_bounds);
// Create the frame and draw it into the graphics context // Create the frame and draw it into the graphics context
frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), p_path, NULL); frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), p_path, NULL);
...@@ -947,18 +886,16 @@ static offscreen_bitmap_t *Compose( int i_text_align, ...@@ -947,18 +886,16 @@ static offscreen_bitmap_t *Compose( int i_text_align,
CGPathRelease(p_path); CGPathRelease(p_path);
// Set up black outlining of the text -- // Set up black outlining of the text --
CGContextSetRGBStrokeColor( p_context, 0, 0, 0, 0.5 ); CGContextSetRGBStrokeColor(p_context, 0, 0, 0, 0.5);
CGContextSetTextDrawingMode( p_context, kCGTextFillStroke ); CGContextSetTextDrawingMode(p_context, kCGTextFillStroke);
if( frame != NULL ) if (frame != NULL) {
{
CFArrayRef lines; CFArrayRef lines;
CGPoint penPosition; CGPoint penPosition;
lines = CTFrameGetLines( frame ); lines = CTFrameGetLines(frame);
penPosition.y = i_height; penPosition.y = i_height;
for (int i=0; i<CFArrayGetCount( lines ); i++) for (int i=0; i<CFArrayGetCount(lines); i++) {
{
CGFloat ascent, descent, leading; CGFloat ascent, descent, leading;
CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, i); CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, i);
...@@ -967,13 +904,13 @@ static offscreen_bitmap_t *Compose( int i_text_align, ...@@ -967,13 +904,13 @@ static offscreen_bitmap_t *Compose( int i_text_align,
// Set the outlining for this line to be dependant on the size of the line - // Set the outlining for this line to be dependant on the size of the line -
// make it about 5% of the ascent, with a minimum at 1.0 // make it about 5% of the ascent, with a minimum at 1.0
float f_thickness = ascent * 0.05; float f_thickness = ascent * 0.05;
CGContextSetLineWidth( p_context, (( f_thickness > 1.0 ) ? 1.0 : f_thickness )); CGContextSetLineWidth(p_context, ((f_thickness > 1.0) ? 1.0 : f_thickness));
double penOffset = CTLineGetPenOffsetForFlush(line, horiz_flush, (i_width - HORIZONTAL_MARGIN*2)); double penOffset = CTLineGetPenOffsetForFlush(line, horiz_flush, (i_width - HORIZONTAL_MARGIN*2));
penPosition.x = HORIZONTAL_MARGIN + penOffset; penPosition.x = HORIZONTAL_MARGIN + penOffset;
penPosition.y -= ascent; penPosition.y -= ascent;
CGContextSetTextPosition( p_context, penPosition.x, penPosition.y ); CGContextSetTextPosition(p_context, penPosition.x, penPosition.y);
CTLineDraw( line, p_context ); CTLineDraw(line, p_context);
penPosition.y -= descent + leading; penPosition.y -= descent + leading;
} }
...@@ -983,21 +920,21 @@ static offscreen_bitmap_t *Compose( int i_text_align, ...@@ -983,21 +920,21 @@ static offscreen_bitmap_t *Compose( int i_text_align,
} }
CFRelease(framesetter); CFRelease(framesetter);
} }
CGContextFlush( p_context ); CGContextFlush(p_context);
CGContextRelease( p_context ); CGContextRelease(p_context);
} }
if( p_colorSpace ) CGColorSpaceRelease( p_colorSpace ); if (p_colorSpace) CGColorSpaceRelease(p_colorSpace);
return p_offScreen; return p_offScreen;
} }
static int GetFontSize( filter_t *p_filter ) static int GetFontSize(filter_t *p_filter)
{ {
return p_filter->fmt_out.video.i_height / DEFAULT_REL_FONT_SIZE; return p_filter->fmt_out.video.i_height / DEFAULT_REL_FONT_SIZE;
} }
static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, static int RenderYUVA(filter_t *p_filter, subpicture_region_t *p_region,
CFMutableAttributedStringRef p_attrString ) CFMutableAttributedStringRef p_attrString)
{ {
offscreen_bitmap_t *p_offScreen = NULL; offscreen_bitmap_t *p_offScreen = NULL;
unsigned i_textblock_height = 0; unsigned i_textblock_height = 0;
...@@ -1006,38 +943,36 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, ...@@ -1006,38 +943,36 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region,
unsigned i_height = p_filter->fmt_out.video.i_visible_height; unsigned i_height = p_filter->fmt_out.video.i_visible_height;
unsigned i_text_align = p_region->i_align & 0x3; unsigned i_text_align = p_region->i_align & 0x3;
if( !p_attrString ) if (!p_attrString) {
{ msg_Err(p_filter, "Invalid argument to RenderYUVA");
msg_Err( p_filter, "Invalid argument to RenderYUVA" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_offScreen = Compose( i_text_align, p_attrString, p_offScreen = Compose(i_text_align, p_attrString,
i_width, i_height, &i_textblock_height ); i_width, i_height, &i_textblock_height);
if( !p_offScreen ) if (!p_offScreen) {
{ msg_Err(p_filter, "No offscreen buffer");
msg_Err( p_filter, "No offscreen buffer" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
uint8_t *p_dst_y,*p_dst_u,*p_dst_v,*p_dst_a; uint8_t *p_dst_y,*p_dst_u,*p_dst_v,*p_dst_a;
video_format_t fmt; video_format_t fmt;
int i_offset; int i_offset;
unsigned x, y, i_pitch; unsigned i_pitch;
uint8_t i_y, i_u, i_v; // YUV values, derived from incoming RGB uint8_t i_y, i_u, i_v; // YUV values, derived from incoming RGB
// Create a new subpicture region // Create a new subpicture region
memset( &fmt, 0, sizeof(video_format_t) ); memset(&fmt, 0, sizeof(video_format_t));
fmt.i_chroma = VLC_CODEC_YUVA; fmt.i_chroma = VLC_CODEC_YUVA;
fmt.i_width = fmt.i_visible_width = i_width; fmt.i_width = fmt.i_visible_width = i_width;
fmt.i_height = fmt.i_visible_height = __MIN( i_height, i_textblock_height + VERTICAL_MARGIN * 2); fmt.i_height = fmt.i_visible_height = __MIN(i_height, i_textblock_height + VERTICAL_MARGIN * 2);
fmt.i_x_offset = fmt.i_y_offset = 0; fmt.i_x_offset = fmt.i_y_offset = 0;
fmt.i_sar_num = 1; fmt.i_sar_num = 1;
fmt.i_sar_den = 1; fmt.i_sar_den = 1;
p_region->p_picture = picture_NewFromFormat( &fmt ); p_region->p_picture = picture_NewFromFormat(&fmt);
if( !p_region->p_picture ) if (!p_region->p_picture)
return VLC_EGENERIC; return VLC_EGENERIC;
p_region->fmt = fmt; p_region->fmt = fmt;
...@@ -1048,20 +983,18 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, ...@@ -1048,20 +983,18 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region,
i_pitch = p_region->p_picture->A_PITCH; i_pitch = p_region->p_picture->A_PITCH;
i_offset = (i_height + VERTICAL_MARGIN < fmt.i_height) ? VERTICAL_MARGIN *i_pitch : 0 ; i_offset = (i_height + VERTICAL_MARGIN < fmt.i_height) ? VERTICAL_MARGIN *i_pitch : 0 ;
for( y = 0; y < fmt.i_height; y++) for (unsigned y = 0; y < fmt.i_height; y++) {
{ for (unsigned x = 0; x < fmt.i_width; x++) {
for( x = 0; x < fmt.i_width; x++)
{
int i_alpha = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel ]; int i_alpha = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel ];
int i_red = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel + 1 ]; int i_red = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel + 1 ];
int i_green = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel + 2 ]; int i_green = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel + 2 ];
int i_blue = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel + 3 ]; int i_blue = p_offScreen->p_data[ y * p_offScreen->i_bytesPerRow + x * p_offScreen->i_bytesPerPixel + 3 ];
i_y = (uint8_t)__MIN(abs( 2104 * i_red + 4130 * i_green + i_y = (uint8_t)__MIN(abs(2104 * i_red + 4130 * i_green +
802 * i_blue + 4096 + 131072 ) >> 13, 235); 802 * i_blue + 4096 + 131072) >> 13, 235);
i_u = (uint8_t)__MIN(abs( -1214 * i_red + -2384 * i_green + i_u = (uint8_t)__MIN(abs(-1214 * i_red + -2384 * i_green +
3598 * i_blue + 4096 + 1048576) >> 13, 240); 3598 * i_blue + 4096 + 1048576) >> 13, 240);
i_v = (uint8_t)__MIN(abs( 3598 * i_red + -3013 * i_green + i_v = (uint8_t)__MIN(abs(3598 * i_red + -3013 * i_green +
-585 * i_blue + 4096 + 1048576) >> 13, 240); -585 * i_blue + 4096 + 1048576) >> 13, 240);
p_dst_y[ i_offset + x ] = i_y; p_dst_y[ i_offset + x ] = i_y;
...@@ -1072,8 +1005,8 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region, ...@@ -1072,8 +1005,8 @@ static int RenderYUVA( filter_t *p_filter, subpicture_region_t *p_region,
i_offset += i_pitch; i_offset += i_pitch;
} }
free( p_offScreen->p_data ); free(p_offScreen->p_data);
free( p_offScreen ); free(p_offScreen);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment