| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
#ifdef HAVE_CONFIG_H |
|---|
| 31 |
# include "config.h" |
|---|
| 32 |
#endif |
|---|
| 33 |
|
|---|
| 34 |
#include <vlc_common.h> |
|---|
| 35 |
#include <vlc_plugin.h> |
|---|
| 36 |
#include <vlc_vout.h> |
|---|
| 37 |
#include <vlc_osd.h> |
|---|
| 38 |
#include <vlc_block.h> |
|---|
| 39 |
#include <vlc_filter.h> |
|---|
| 40 |
#include <vlc_stream.h> |
|---|
| 41 |
#include <vlc_xml.h> |
|---|
| 42 |
#include <vlc_input.h> |
|---|
| 43 |
#include <vlc_strings.h> |
|---|
| 44 |
|
|---|
| 45 |
#include <math.h> |
|---|
| 46 |
#include <errno.h> |
|---|
| 47 |
|
|---|
| 48 |
#include <ft2build.h> |
|---|
| 49 |
#include FT_FREETYPE_H |
|---|
| 50 |
#include FT_GLYPH_H |
|---|
| 51 |
#define FT_FLOOR(X) ((X & -64) >> 6) |
|---|
| 52 |
#define FT_CEIL(X) (((X + 63) & -64) >> 6) |
|---|
| 53 |
#define FT_MulFix(v, s) (((v)*(s))>>16) |
|---|
| 54 |
|
|---|
| 55 |
#ifdef __APPLE__ |
|---|
| 56 |
#define DEFAULT_FONT "/System/Library/Fonts/LucidaGrande.dfont" |
|---|
| 57 |
#define FC_DEFAULT_FONT "Lucida Grande" |
|---|
| 58 |
#elif defined( SYS_BEOS ) |
|---|
| 59 |
#define DEFAULT_FONT "/boot/beos/etc/fonts/ttfonts/Swiss721.ttf" |
|---|
| 60 |
#define FC_DEFAULT_FONT "Swiss" |
|---|
| 61 |
#elif defined( WIN32 ) |
|---|
| 62 |
#define DEFAULT_FONT "" |
|---|
| 63 |
#define FC_DEFAULT_FONT "Arial" |
|---|
| 64 |
#else |
|---|
| 65 |
#define DEFAULT_FONT "/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf" |
|---|
| 66 |
#define FC_DEFAULT_FONT "Serif Bold" |
|---|
| 67 |
#endif |
|---|
| 68 |
|
|---|
| 69 |
#if defined(HAVE_FRIBIDI) |
|---|
| 70 |
#include <fribidi/fribidi.h> |
|---|
| 71 |
#endif |
|---|
| 72 |
|
|---|
| 73 |
#ifdef HAVE_FONTCONFIG |
|---|
| 74 |
#include <fontconfig/fontconfig.h> |
|---|
| 75 |
#endif |
|---|
| 76 |
|
|---|
| 77 |
#include <assert.h> |
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
static int Create ( vlc_object_t * ); |
|---|
| 83 |
static void Destroy( vlc_object_t * ); |
|---|
| 84 |
|
|---|
| 85 |
#define FONT_TEXT N_("Font") |
|---|
| 86 |
#define FONT_LONGTEXT N_("Filename for the font you want to use") |
|---|
| 87 |
#define FONTSIZE_TEXT N_("Font size in pixels") |
|---|
| 88 |
#define FONTSIZE_LONGTEXT N_("This is the default size of the fonts " \ |
|---|
| 89 |
"that will be rendered on the video. " \ |
|---|
| 90 |
"If set to something different than 0 this option will override the " \ |
|---|
| 91 |
"relative font size." ) |
|---|
| 92 |
#define OPACITY_TEXT N_("Opacity") |
|---|
| 93 |
#define OPACITY_LONGTEXT N_("The opacity (inverse of transparency) of the " \ |
|---|
| 94 |
"text that will be rendered on the video. 0 = transparent, " \ |
|---|
| 95 |
"255 = totally opaque. " ) |
|---|
| 96 |
#define COLOR_TEXT N_("Text default color") |
|---|
| 97 |
#define COLOR_LONGTEXT N_("The color of the text that will be rendered on "\ |
|---|
| 98 |
"the video. This must be an hexadecimal (like HTML colors). The first two "\ |
|---|
| 99 |
"chars are for red, then green, then blue. #000000 = black, #FF0000 = red,"\ |
|---|
| 100 |
" #00FF00 = green, #FFFF00 = yellow (red + green), #FFFFFF = white" ) |
|---|
| 101 |
#define FONTSIZER_TEXT N_("Relative font size") |
|---|
| 102 |
#define FONTSIZER_LONGTEXT N_("This is the relative default size of the " \ |
|---|
| 103 |
"fonts that will be rendered on the video. If absolute font size is set, "\ |
|---|
| 104 |
"relative size will be overriden." ) |
|---|
| 105 |
|
|---|
| 106 |
static const int pi_sizes[] = { 20, 18, 16, 12, 6 }; |
|---|
| 107 |
static const char *const ppsz_sizes_text[] = { |
|---|
| 108 |
N_("Smaller"), N_("Small"), N_("Normal"), N_("Large"), N_("Larger") }; |
|---|
| 109 |
#define YUVP_TEXT N_("Use YUVP renderer") |
|---|
| 110 |
#define YUVP_LONGTEXT N_("This renders the font using \"paletized YUV\". " \ |
|---|
| 111 |
"This option is only needed if you want to encode into DVB subtitles" ) |
|---|
| 112 |
#define EFFECT_TEXT N_("Font Effect") |
|---|
| 113 |
#define EFFECT_LONGTEXT N_("It is possible to apply effects to the rendered " \ |
|---|
| 114 |
"text to improve its readability." ) |
|---|
| 115 |
|
|---|
| 116 |
#define EFFECT_BACKGROUND 1 |
|---|
| 117 |
#define EFFECT_OUTLINE 2 |
|---|
| 118 |
#define EFFECT_OUTLINE_FAT 3 |
|---|
| 119 |
|
|---|
| 120 |
static int const pi_effects[] = { 1, 2, 3 }; |
|---|
| 121 |
static const char *const ppsz_effects_text[] = { |
|---|
| 122 |
N_("Background"),N_("Outline"), N_("Fat Outline") }; |
|---|
| 123 |
static const int pi_color_values[] = { |
|---|
| 124 |
0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000, |
|---|
| 125 |
0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00808000, 0x00008000, 0x00008080, |
|---|
| 126 |
0x0000FF00, 0x00800080, 0x00000080, 0x000000FF, 0x0000FFFF }; |
|---|
| 127 |
|
|---|
| 128 |
static const char *const ppsz_color_descriptions[] = { |
|---|
| 129 |
N_("Black"), N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"), |
|---|
| 130 |
N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"), N_("Teal"), |
|---|
| 131 |
N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"), N_("Aqua") }; |
|---|
| 132 |
|
|---|
| 133 |
vlc_module_begin(); |
|---|
| 134 |
set_shortname( N_("Text renderer")); |
|---|
| 135 |
set_description( N_("Freetype2 font renderer") ); |
|---|
| 136 |
set_category( CAT_VIDEO ); |
|---|
| 137 |
set_subcategory( SUBCAT_VIDEO_SUBPIC ); |
|---|
| 138 |
|
|---|
| 139 |
add_file( "freetype-font", DEFAULT_FONT, NULL, FONT_TEXT, FONT_LONGTEXT, |
|---|
| 140 |
false ); |
|---|
| 141 |
|
|---|
| 142 |
add_integer( "freetype-fontsize", 0, NULL, FONTSIZE_TEXT, |
|---|
| 143 |
FONTSIZE_LONGTEXT, true ); |
|---|
| 144 |
|
|---|
| 145 |
|
|---|
| 146 |
add_integer_with_range( "freetype-opacity", 255, 0, 255, NULL, |
|---|
| 147 |
OPACITY_TEXT, OPACITY_LONGTEXT, true ); |
|---|
| 148 |
|
|---|
| 149 |
|
|---|
| 150 |
add_integer( "freetype-color", 0x00FFFFFF, NULL, COLOR_TEXT, |
|---|
| 151 |
COLOR_LONGTEXT, false ); |
|---|
| 152 |
change_integer_list( pi_color_values, ppsz_color_descriptions, NULL ); |
|---|
| 153 |
|
|---|
| 154 |
add_integer( "freetype-rel-fontsize", 16, NULL, FONTSIZER_TEXT, |
|---|
| 155 |
FONTSIZER_LONGTEXT, false ); |
|---|
| 156 |
change_integer_list( pi_sizes, ppsz_sizes_text, NULL ); |
|---|
| 157 |
add_integer( "freetype-effect", 2, NULL, EFFECT_TEXT, |
|---|
| 158 |
EFFECT_LONGTEXT, false ); |
|---|
| 159 |
change_integer_list( pi_effects, ppsz_effects_text, NULL ); |
|---|
| 160 |
|
|---|
| 161 |
add_bool( "freetype-yuvp", 0, NULL, YUVP_TEXT, |
|---|
| 162 |
YUVP_LONGTEXT, true ); |
|---|
| 163 |
set_capability( "text renderer", 100 ); |
|---|
| 164 |
add_shortcut( "text" ); |
|---|
| 165 |
set_callbacks( Create, Destroy ); |
|---|
| 166 |
vlc_module_end(); |
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 |
|
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 |
|
|---|
| 173 |
|
|---|
| 174 |
|
|---|
| 175 |
static int RenderText( filter_t *, subpicture_region_t *, |
|---|
| 176 |
subpicture_region_t * ); |
|---|
| 177 |
#ifdef HAVE_FONTCONFIG |
|---|
| 178 |
static int RenderHtml( filter_t *, subpicture_region_t *, |
|---|
| 179 |
subpicture_region_t * ); |
|---|
| 180 |
static char *FontConfig_Select( FcConfig *, const char *, |
|---|
| 181 |
bool, bool, int * ); |
|---|
| 182 |
#endif |
|---|
| 183 |
|
|---|
| 184 |
|
|---|
| 185 |
static int LoadFontsFromAttachments( filter_t *p_filter ); |
|---|
| 186 |
|
|---|
| 187 |
static int GetFontSize( filter_t *p_filter ); |
|---|
| 188 |
static int SetFontSize( filter_t *, int ); |
|---|
| 189 |
static void YUVFromRGB( uint32_t i_argb, |
|---|
| 190 |
uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v ); |
|---|
| 191 |
|
|---|
| 192 |
typedef struct line_desc_t line_desc_t; |
|---|
| 193 |
struct line_desc_t |
|---|
| 194 |
{ |
|---|
| 195 |
|
|---|
| 196 |
FT_BitmapGlyph *pp_glyphs; |
|---|
| 197 |
|
|---|
| 198 |
FT_Vector *p_glyph_pos; |
|---|
| 199 |
|
|---|
| 200 |
|
|---|
| 201 |
|
|---|
| 202 |
|
|---|
| 203 |
uint32_t *p_fg_rgb; |
|---|
| 204 |
uint32_t *p_bg_rgb; |
|---|
| 205 |
uint8_t *p_fg_bg_ratio; |
|---|
| 206 |
bool b_new_color_mode; |
|---|
| 207 |
|
|---|
| 208 |
uint16_t *pi_underline_offset; |
|---|
| 209 |
uint16_t *pi_underline_thickness; |
|---|
| 210 |
|
|---|
| 211 |
int i_height; |
|---|
| 212 |
int i_width; |
|---|
| 213 |
int i_red, i_green, i_blue; |
|---|
| 214 |
int i_alpha; |
|---|
| 215 |
|
|---|
| 216 |
line_desc_t *p_next; |
|---|
| 217 |
}; |
|---|
| 218 |
static line_desc_t *NewLine( int ); |
|---|
| 219 |
|
|---|
| 220 |
typedef struct |
|---|
| 221 |
{ |
|---|
| 222 |
int i_font_size; |
|---|
| 223 |
uint32_t i_font_color; |
|---|
| 224 |
uint32_t i_karaoke_bg_color; |
|---|
| 225 |
bool b_italic; |
|---|
| 226 |
bool b_bold; |
|---|
| 227 |
bool b_underline; |
|---|
| 228 |
char *psz_fontname; |
|---|
| 229 |
} ft_style_t; |
|---|
| 230 |
|
|---|
| 231 |
static int Render( filter_t *, subpicture_region_t *, line_desc_t *, int, int); |
|---|
| 232 |
static void FreeLines( line_desc_t * ); |
|---|
| 233 |
static void FreeLine( line_desc_t * ); |
|---|
| 234 |
|
|---|
| 235 |
#ifdef HAVE_FONTCONFIG |
|---|
| 236 |
static vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock ); |
|---|
| 237 |
static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ); |
|---|
| 238 |
static void* FontBuilderThread( vlc_object_t *p_this); |
|---|
| 239 |
static void FontBuilderDestructor( vlc_object_t *p_this ); |
|---|
| 240 |
static void FontBuilderGetFcConfig( filter_t *p_filter, vlc_object_t *p_fontbuilder ); |
|---|
| 241 |
static int FontBuilderDone( vlc_object_t*, const char *, vlc_value_t, vlc_value_t, |
|---|
| 242 |
void* ); |
|---|
| 243 |
#endif |
|---|
| 244 |
|
|---|
| 245 |
|
|---|
| 246 |
|
|---|
| 247 |
|
|---|
| 248 |
|
|---|
| 249 |
|
|---|
| 250 |
|
|---|
| 251 |
struct filter_sys_t |
|---|
| 252 |
{ |
|---|
| 253 |
FT_Library p_library; |
|---|
| 254 |
FT_Face p_face; |
|---|
| 255 |
bool i_use_kerning; |
|---|
| 256 |
uint8_t i_font_opacity; |
|---|
| 257 |
int i_font_color; |
|---|
| 258 |
int i_font_size; |
|---|
| 259 |
int i_effect; |
|---|
| 260 |
|
|---|
| 261 |
int i_default_font_size; |
|---|
| 262 |
int i_display_height; |
|---|
| 263 |
#ifdef HAVE_FONTCONFIG |
|---|
| 264 |
vlc_mutex_t *p_fontconfig_lock; |
|---|
| 265 |
bool b_fontconfig_ok; |
|---|
| 266 |
FcConfig *p_fontconfig; |
|---|
| 267 |
#endif |
|---|
| 268 |
|
|---|
| 269 |
input_attachment_t **pp_font_attachments; |
|---|
| 270 |
int i_font_attachments; |
|---|
| 271 |
|
|---|
| 272 |
vlc_object_t *p_fontbuilder; |
|---|
| 273 |
}; |
|---|
| 274 |
|
|---|
| 275 |
#define UCHAR uint32_t |
|---|
| 276 |
#define TR_DEFAULT_FONT FC_DEFAULT_FONT |
|---|
| 277 |
#define TR_FONT_STYLE_PTR ft_style_t * |
|---|
| 278 |
|
|---|
| 279 |
#include "text_renderer.h" |
|---|
| 280 |
|
|---|
| 281 |
|
|---|
| 282 |
|
|---|
| 283 |
|
|---|
| 284 |
|
|---|
| 285 |
|
|---|
| 286 |
static int Create( vlc_object_t *p_this ) |
|---|
| 287 |
{ |
|---|
| 288 |
filter_t *p_filter = (filter_t *)p_this; |
|---|
| 289 |
filter_sys_t *p_sys; |
|---|
| 290 |
char *psz_fontfile = NULL; |
|---|
| 291 |
int i_error; |
|---|
| 292 |
vlc_value_t val; |
|---|
| 293 |
|
|---|
| 294 |
|
|---|
| 295 |
p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) ); |
|---|
| 296 |
if( !p_sys ) |
|---|
| 297 |
return VLC_ENOMEM; |
|---|
| 298 |
p_sys->p_face = 0; |
|---|
| 299 |
p_sys->p_library = 0; |
|---|
| 300 |
p_sys->i_font_size = 0; |
|---|
| 301 |
p_sys->i_display_height = 0; |
|---|
| 302 |
|
|---|
| 303 |
var_Create( p_filter, "freetype-font", |
|---|
| 304 |
VLC_VAR_STRING | VLC_VAR_DOINHERIT ); |
|---|
| 305 |
var_Create( p_filter, "freetype-fontsize", |
|---|
| 306 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 307 |
var_Create( p_filter, "freetype-rel-fontsize", |
|---|
| 308 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 309 |
var_Create( p_filter, "freetype-opacity", |
|---|
| 310 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 311 |
var_Create( p_filter, "freetype-effect", |
|---|
| 312 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 313 |
var_Get( p_filter, "freetype-opacity", &val ); |
|---|
| 314 |
p_sys->i_font_opacity = __MAX( __MIN( val.i_int, 255 ), 0 ); |
|---|
| 315 |
var_Create( p_filter, "freetype-color", |
|---|
| 316 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 317 |
var_Get( p_filter, "freetype-color", &val ); |
|---|
| 318 |
p_sys->i_font_color = __MAX( __MIN( val.i_int, 0xFFFFFF ), 0 ); |
|---|
| 319 |
p_sys->i_effect = var_GetInteger( p_filter, "freetype-effect" ); |
|---|
| 320 |
|
|---|
| 321 |
|
|---|
| 322 |
var_Get( p_filter, "freetype-font", &val ); |
|---|
| 323 |
psz_fontfile = val.psz_string; |
|---|
| 324 |
if( !psz_fontfile || !*psz_fontfile ) |
|---|
| 325 |
{ |
|---|
| 326 |
free( psz_fontfile ); |
|---|
| 327 |
psz_fontfile = (char *)malloc( PATH_MAX + 1 ); |
|---|
| 328 |
if( !psz_fontfile ) |
|---|
| 329 |
goto error; |
|---|
| 330 |
#ifdef WIN32 |
|---|
| 331 |
GetWindowsDirectory( psz_fontfile, PATH_MAX + 1 ); |
|---|
| 332 |
strcat( psz_fontfile, "\\fonts\\arial.ttf" ); |
|---|
| 333 |
#elif defined(__APPLE__) |
|---|
| 334 |
strcpy( psz_fontfile, DEFAULT_FONT ); |
|---|
| 335 |
#else |
|---|
| 336 |
msg_Err( p_filter, "user didn't specify a font" ); |
|---|
| 337 |
goto error; |
|---|
| 338 |
#endif |
|---|
| 339 |
} |
|---|
| 340 |
|
|---|
| 341 |
i_error = FT_Init_FreeType( &p_sys->p_library ); |
|---|
| 342 |
if( i_error ) |
|---|
| 343 |
{ |
|---|
| 344 |
msg_Err( p_filter, "couldn't initialize freetype" ); |
|---|
| 345 |
goto error; |
|---|
| 346 |
} |
|---|
| 347 |
i_error = FT_New_Face( p_sys->p_library, psz_fontfile ? psz_fontfile : "", |
|---|
| 348 |
0, &p_sys->p_face ); |
|---|
| 349 |
if( i_error == FT_Err_Unknown_File_Format ) |
|---|
| 350 |
{ |
|---|
| 351 |
msg_Err( p_filter, "file %s have unknown format", psz_fontfile ); |
|---|
| 352 |
goto error; |
|---|
| 353 |
} |
|---|
| 354 |
else if( i_error ) |
|---|
| 355 |
{ |
|---|
| 356 |
msg_Err( p_filter, "failed to load font file %s", psz_fontfile ); |
|---|
| 357 |
goto error; |
|---|
| 358 |
} |
|---|
| 359 |
|
|---|
| 360 |
i_error = FT_Select_Charmap( p_sys->p_face, ft_encoding_unicode ); |
|---|
| 361 |
if( i_error ) |
|---|
| 362 |
{ |
|---|
| 363 |
msg_Err( p_filter, "font has no unicode translation table" ); |
|---|
| 364 |
goto error; |
|---|
| 365 |
} |
|---|
| 366 |
|
|---|
| 367 |
#ifdef HAVE_FONTCONFIG |
|---|
| 368 |
p_sys->b_fontconfig_ok = false; |
|---|
| 369 |
p_sys->p_fontconfig = NULL; |
|---|
| 370 |
p_sys->p_fontbuilder = FontBuilderAttach( p_filter, &p_sys->p_fontconfig_lock ); |
|---|
| 371 |
#endif |
|---|
| 372 |
|
|---|
| 373 |
p_sys->i_use_kerning = FT_HAS_KERNING( p_sys->p_face ); |
|---|
| 374 |
|
|---|
| 375 |
var_Get( p_filter, "freetype-fontsize", &val ); |
|---|
| 376 |
p_sys->i_default_font_size = val.i_int; |
|---|
| 377 |
if( SetFontSize( p_filter, 0 ) != VLC_SUCCESS ) goto error; |
|---|
| 378 |
|
|---|
| 379 |
free( psz_fontfile ); |
|---|
| 380 |
|
|---|
| 381 |
p_sys->pp_font_attachments = NULL; |
|---|
| 382 |
p_sys->i_font_attachments = 0; |
|---|
| 383 |
|
|---|
| 384 |
p_filter->pf_render_text = RenderText; |
|---|
| 385 |
#ifdef HAVE_FONTCONFIG |
|---|
| 386 |
p_filter->pf_render_html = RenderHtml; |
|---|
| 387 |
#else |
|---|
| 388 |
p_filter->pf_render_html = NULL; |
|---|
| 389 |
#endif |
|---|
| 390 |
|
|---|
| 391 |
LoadFontsFromAttachments( p_filter ); |
|---|
| 392 |
|
|---|
| 393 |
return VLC_SUCCESS; |
|---|
| 394 |
|
|---|
| 395 |
error: |
|---|
| 396 |
if( p_sys->p_face ) FT_Done_Face( p_sys->p_face ); |
|---|
| 397 |
if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library ); |
|---|
| 398 |
free( psz_fontfile ); |
|---|
| 399 |
free( p_sys ); |
|---|
| 400 |
return VLC_EGENERIC; |
|---|
| 401 |
} |
|---|
| 402 |
|
|---|
| 403 |
|
|---|
| 404 |
|
|---|
| 405 |
|
|---|
| 406 |
|
|---|
| 407 |
|
|---|
| 408 |
static void Destroy( vlc_object_t *p_this ) |
|---|
| 409 |
{ |
|---|
| 410 |
filter_t *p_filter = (filter_t *)p_this; |
|---|
| 411 |
filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| 412 |
|
|---|
| 413 |
if( p_sys->pp_font_attachments ) |
|---|
| 414 |
{ |
|---|
| 415 |
int k; |
|---|
| 416 |
|
|---|
| 417 |
for( k = 0; k < p_sys->i_font_attachments; k++ ) |
|---|
| 418 |
vlc_input_attachment_Delete( p_sys->pp_font_attachments[k] ); |
|---|
| 419 |
|
|---|
| 420 |
free( p_sys->pp_font_attachments ); |
|---|
| 421 |
} |
|---|
| 422 |
|
|---|
| 423 |
#ifdef HAVE_FONTCONFIG |
|---|
| 424 |
FontBuilderDetach( p_filter, p_sys->p_fontbuilder ); |
|---|
| 425 |
#endif |
|---|
| 426 |
|
|---|
| 427 |
|
|---|
| 428 |
|
|---|
| 429 |
|
|---|
| 430 |
|
|---|
| 431 |
FT_Done_Face( p_sys->p_face ); |
|---|
| 432 |
FT_Done_FreeType( p_sys->p_library ); |
|---|
| 433 |
free( p_sys ); |
|---|
| 434 |
} |
|---|
| 435 |
|
|---|
| 436 |
#ifdef HAVE_FONTCONFIG |
|---|
| 437 |
static vlc_object_t *FontBuilderAttach( filter_t *p_filter, vlc_mutex_t **pp_lock ) |
|---|
| 438 |
{ |
|---|
| 439 |
|
|---|
| 440 |
vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); |
|---|
| 441 |
vlc_object_t *p_fontbuilder = |
|---|
| 442 |
vlc_object_find_name( p_filter->p_libvlc, |
|---|
| 443 |
"fontlist builder", FIND_CHILD ); |
|---|
| 444 |
|
|---|
| 445 |
if( !p_fontbuilder ) |
|---|
| 446 |
{ |
|---|
| 447 |
|
|---|
| 448 |
|
|---|
| 449 |
|
|---|
| 450 |
|
|---|
| 451 |
|
|---|
| 452 |
|
|---|
| 453 |
|
|---|
| 454 |
|
|---|
| 455 |
|
|---|
| 456 |
p_fontbuilder = vlc_object_create( p_filter->p_libvlc, |
|---|
| 457 |
sizeof(vlc_object_t) ); |
|---|
| 458 |
if( p_fontbuilder ) |
|---|
| 459 |
{ |
|---|
| 460 |
p_fontbuilder->psz_object_name = strdup( "fontlist builder" ); |
|---|
| 461 |
p_fontbuilder->p_private = NULL; |
|---|
| 462 |
vlc_object_set_destructor( p_fontbuilder, FontBuilderDestructor ); |
|---|
| 463 |
|
|---|
| 464 |
vlc_object_attach( p_fontbuilder, p_filter->p_libvlc ); |
|---|
| 465 |
|
|---|
| 466 |
var_Create( p_fontbuilder, "build-done", VLC_VAR_BOOL ); |
|---|
| 467 |
var_SetBool( p_fontbuilder, "build-done", false ); |
|---|
| 468 |
|
|---|
| 469 |
if( vlc_thread_create( p_fontbuilder, |
|---|
| 470 |
"fontlist builder", |
|---|
| 471 |
FontBuilderThread, |
|---|
| 472 |
VLC_THREAD_PRIORITY_LOW, |
|---|
| 473 |
false ) ) |
|---|
| 474 |
{ |
|---|
| 475 |
msg_Warn( p_filter, "fontconfig database builder thread can't " |
|---|
| 476 |
"be launched. Font styling support will be limited." ); |
|---|
| 477 |
} |
|---|
| 478 |
} |
|---|
| 479 |
} |
|---|
| 480 |
if( p_fontbuilder ) |
|---|
| 481 |
{ |
|---|
| 482 |
var_AddCallback( p_fontbuilder, "build-done", FontBuilderDone, p_filter ); |
|---|
| 483 |
FontBuilderGetFcConfig( p_filter, p_fontbuilder ); |
|---|
| 484 |
} |
|---|
| 485 |
vlc_mutex_unlock( p_lock ); |
|---|
| 486 |
*pp_lock = p_lock; |
|---|
| 487 |
return p_fontbuilder; |
|---|
| 488 |
} |
|---|
| 489 |
static void FontBuilderDetach( filter_t *p_filter, vlc_object_t *p_fontbuilder ) |
|---|
| 490 |
{ |
|---|
| 491 |
vlc_mutex_t *lock = var_AcquireMutex( "fontbuilder" ); |
|---|
| 492 |
if( p_fontbuilder ) |
|---|
| 493 |
{ |
|---|
| 494 |
const bool b_alive = vlc_object_alive( p_fontbuilder ); |
|---|
| 495 |
|
|---|
| 496 |
var_DelCallback( p_fontbuilder, "build-done", FontBuilderDone, p_filter ); |
|---|
| 497 |
|
|---|
| 498 |
|
|---|
| 499 |
if( b_alive ) |
|---|
| 500 |
{ |
|---|
| 501 |
vlc_object_kill( p_fontbuilder ); |
|---|
| 502 |
vlc_mutex_unlock( lock ); |
|---|
| 503 |
|
|---|
| 504 |
|
|---|
| 505 |
|
|---|
| 506 |
|
|---|
| 507 |
vlc_thread_join( p_fontbuilder ); |
|---|
| 508 |
|
|---|
| 509 |
vlc_mutex_lock( lock ); |
|---|
| 510 |
} |
|---|
| 511 |
vlc_object_release( p_fontbuilder ); |
|---|
| 512 |
} |
|---|
| 513 |
vlc_mutex_unlock( lock ); |
|---|
| 514 |
} |
|---|
| 515 |
static void* FontBuilderThread( vlc_object_t *p_this ) |
|---|
| 516 |
{ |
|---|
| 517 |
FcConfig *p_fontconfig = FcInitLoadConfig(); |
|---|
| 518 |
|
|---|
| 519 |
vlc_thread_ready( p_this ); |
|---|
| 520 |
|
|---|
| 521 |
if( p_fontconfig ) |
|---|
| 522 |
{ |
|---|
| 523 |
mtime_t t1, t2; |
|---|
| 524 |
int canc = vlc_savecancel (); |
|---|
| 525 |
|
|---|
| 526 |
|
|---|
| 527 |
msg_Dbg( p_this, "Building font database..." ); |
|---|
| 528 |
t1 = mdate(); |
|---|
| 529 |
if(! FcConfigBuildFonts( p_fontconfig )) |
|---|
| 530 |
{ |
|---|
| 531 |
|
|---|
| 532 |
|
|---|
| 533 |
|
|---|
| 534 |
|
|---|
| 535 |
msg_Err( p_this, "fontconfig database can't be built. " |
|---|
| 536 |
"Font styling won't be available" ); |
|---|
| 537 |
} |
|---|
| 538 |
t2 = mdate(); |
|---|
| 539 |
|
|---|
| 540 |
msg_Dbg( p_this, "Finished building font database." ); |
|---|
| 541 |
msg_Dbg( p_this, "Took %ld seconds", (long)((t2 - t1)/1000000) ); |
|---|
| 542 |
|
|---|
| 543 |
vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); |
|---|
| 544 |
p_this->p_private = p_fontconfig; |
|---|
| 545 |
vlc_mutex_unlock( p_lock ); |
|---|
| 546 |
|
|---|
| 547 |
var_SetBool( p_this, "build-done", true ); |
|---|
| 548 |
vlc_restorecancel (canc); |
|---|
| 549 |
} |
|---|
| 550 |
return NULL; |
|---|
| 551 |
} |
|---|
| 552 |
static void FontBuilderGetFcConfig( filter_t *p_filter, vlc_object_t *p_fontbuilder ) |
|---|
| 553 |
{ |
|---|
| 554 |
filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| 555 |
|
|---|
| 556 |
p_sys->p_fontconfig = p_fontbuilder->p_private; |
|---|
| 557 |
p_sys->b_fontconfig_ok = p_fontbuilder->p_private != NULL; |
|---|
| 558 |
} |
|---|
| 559 |
static void FontBuilderDestructor( vlc_object_t *p_this ) |
|---|
| 560 |
{ |
|---|
| 561 |
FcConfig *p_fontconfig = p_this->p_private; |
|---|
| 562 |
|
|---|
| 563 |
if( p_fontconfig ) |
|---|
| 564 |
FcConfigDestroy( p_fontconfig ); |
|---|
| 565 |
} |
|---|
| 566 |
static int FontBuilderDone( vlc_object_t *p_this, const char *psz_var, |
|---|
| 567 |
vlc_value_t oldval, vlc_value_t newval, void *param ) |
|---|
| 568 |
{ |
|---|
| 569 |
filter_t *p_filter = param; |
|---|
| 570 |
|
|---|
| 571 |
if( newval.b_bool ) |
|---|
| 572 |
{ |
|---|
| 573 |
vlc_mutex_t *p_lock = var_AcquireMutex( "fontbuilder" ); |
|---|
| 574 |
|
|---|
| 575 |
FontBuilderGetFcConfig( p_filter, p_this ); |
|---|
| 576 |
|
|---|
| 577 |
vlc_mutex_unlock( p_lock ); |
|---|
| 578 |
} |
|---|
| 579 |
|
|---|
| 580 |
VLC_UNUSED(psz_var); |
|---|
| 581 |
VLC_UNUSED(oldval); |
|---|
| 582 |
return VLC_SUCCESS; |
|---|
| 583 |
} |
|---|
| 584 |
#endif |
|---|
| 585 |
|
|---|
| 586 |
|
|---|
| 587 |
|
|---|
| 588 |
|
|---|
| 589 |
|
|---|
| 590 |
static int LoadFontsFromAttachments( filter_t *p_filter ) |
|---|
| 591 |
{ |
|---|
| 592 |
filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| 593 |
input_thread_t *p_input; |
|---|
| 594 |
input_attachment_t **pp_attachments; |
|---|
| 595 |
int i_attachments_cnt; |
|---|
| 596 |
int k; |
|---|
| 597 |
int rv = VLC_SUCCESS; |
|---|
| 598 |
|
|---|
| 599 |
p_input = (input_thread_t *)vlc_object_find( p_filter, VLC_OBJECT_INPUT, FIND_PARENT ); |
|---|
| 600 |
if( ! p_input ) |
|---|
| 601 |
return VLC_EGENERIC; |
|---|
| 602 |
|
|---|
| 603 |
if( VLC_SUCCESS != input_Control( p_input, INPUT_GET_ATTACHMENTS, &pp_attachments, &i_attachments_cnt )) |
|---|
| 604 |
{ |
|---|
| 605 |
vlc_object_release(p_input); |
|---|
| 606 |
return VLC_EGENERIC; |
|---|
| 607 |
} |
|---|
| 608 |
|
|---|
| 609 |
p_sys->i_font_attachments = 0; |
|---|
| 610 |
p_sys->pp_font_attachments = malloc( i_attachments_cnt * sizeof( input_attachment_t * )); |
|---|
| 611 |
if(! p_sys->pp_font_attachments ) |
|---|
| 612 |
rv = VLC_ENOMEM; |
|---|
| 613 |
|
|---|
| 614 |
for( k = 0; k < i_attachments_cnt; k++ ) |
|---|
| 615 |
{ |
|---|
| 616 |
input_attachment_t *p_attach = pp_attachments[k]; |
|---|
| 617 |
|
|---|
| 618 |
if( p_sys->pp_font_attachments ) |
|---|
| 619 |
{ |
|---|
| 620 |
if(( !strcmp( p_attach->psz_mime, "application/x-truetype-font" ) || |
|---|
| 621 |
!strcmp( p_attach->psz_mime, "application/x-font-otf" ) ) && |
|---|
| 622 |
( p_attach->i_data > 0 ) && |
|---|
| 623 |
( p_attach->p_data != NULL ) ) |
|---|
| 624 |
{ |
|---|
| 625 |
p_sys->pp_font_attachments[ p_sys->i_font_attachments++ ] = p_attach; |
|---|
| 626 |
} |
|---|
| 627 |
else |
|---|
| 628 |
{ |
|---|
| 629 |
vlc_input_attachment_Delete( p_attach ); |
|---|
| 630 |
} |
|---|
| 631 |
} |
|---|
| 632 |
else |
|---|
| 633 |
{ |
|---|
| 634 |
vlc_input_attachment_Delete( p_attach ); |
|---|
| 635 |
} |
|---|
| 636 |
} |
|---|
| 637 |
free( pp_attachments ); |
|---|
| 638 |
|
|---|
| 639 |
vlc_object_release(p_input); |
|---|
| 640 |
|
|---|
| 641 |
return rv; |
|---|
| 642 |
} |
|---|
| 643 |
|
|---|
| 644 |
|
|---|
| 645 |
|
|---|
| 646 |
|
|---|
| 647 |
|
|---|
| 648 |
|
|---|
| 649 |
static int Render( filter_t *p_filter, subpicture_region_t *p_region, |
|---|
| 650 |
line_desc_t *p_line, int i_width, int i_height ) |
|---|
| 651 |
{ |
|---|
| 652 |
static const uint8_t pi_gamma[16] = |
|---|
| 653 |
{0x00, 0x52, 0x84, 0x96, 0xb8, 0xca, 0xdc, 0xee, 0xff, |
|---|
| 654 |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
|---|
| 655 |
|
|---|
| 656 |
uint8_t *p_dst; |
|---|
| 657 |
video_format_t fmt; |
|---|
| 658 |
int i, x, y, i_pitch; |
|---|
| 659 |
uint8_t i_y; |
|---|
| 660 |
int8_t i_u, i_v; |
|---|
| 661 |
|
|---|
| 662 |
|
|---|
| 663 |
memset( &fmt, 0, sizeof(video_format_t) ); |
|---|
| 664 |
fmt.i_chroma = VLC_FOURCC('Y','U','V','P'); |
|---|
| 665 |
fmt.i_aspect = 0; |
|---|
| 666 |
fmt.i_width = fmt.i_visible_width = i_width + 4; |
|---|
| 667 |
fmt.i_height = fmt.i_visible_height = i_height + 4; |
|---|
| 668 |
if( p_region->fmt.i_visible_width > 0 ) |
|---|
| 669 |
fmt.i_visible_width = p_region->fmt.i_visible_width; |
|---|
| 670 |
if( p_region->fmt.i_visible_height > 0 ) |
|---|
| 671 |
fmt.i_visible_height = p_region->fmt.i_visible_height; |
|---|
| 672 |
fmt.i_x_offset = fmt.i_y_offset = 0; |
|---|
| 673 |
|
|---|
| 674 |
assert( !p_region->p_picture ); |
|---|
| 675 |
p_region->p_picture = picture_New( fmt.i_chroma, fmt.i_width, fmt.i_height, fmt.i_aspect ); |
|---|
| 676 |
if( !p_region->p_picture ) |
|---|
| 677 |
return VLC_EGENERIC; |
|---|
| 678 |
p_region->fmt = fmt; |
|---|
| 679 |
|
|---|
| 680 |
|
|---|
| 681 |
i_y = (uint8_t)(( 66 * p_line->i_red + 129 * p_line->i_green + |
|---|
| 682 |
25 * p_line->i_blue + 128) >> 8) + 16; |
|---|
| 683 |
i_u = (int8_t)(( -38 * p_line->i_red - 74 * p_line->i_green + |
|---|
| 684 |
112 * p_line->i_blue + 128) >> 8) + 128; |
|---|
| 685 |
i_v = (int8_t)(( 112 * p_line->i_red - 94 * p_line->i_green - |
|---|
| 686 |
18 * p_line->i_blue + 128) >> 8) + 128; |
|---|
| 687 |
|
|---|
| 688 |
|
|---|
| 689 |
fmt.p_palette->i_entries = 16; |
|---|
| 690 |
for( i = 0; i < 8; i++ ) |
|---|
| 691 |
{ |
|---|
| 692 |
fmt.p_palette->palette[i][0] = 0; |
|---|
| 693 |
fmt.p_palette->palette[i][1] = 0x80; |
|---|
| 694 |
fmt.p_palette->palette[i][2] = 0x80; |
|---|
| 695 |
fmt.p_palette->palette[i][3] = pi_gamma[i]; |
|---|
| 696 |
fmt.p_palette->palette[i][3] = |
|---|
| 697 |
(int)fmt.p_palette->palette[i][3] * (255 - p_line->i_alpha) / 255; |
|---|
| 698 |
} |
|---|
| 699 |
for( i = 8; i < fmt.p_palette->i_entries; i++ ) |
|---|
| 700 |
{ |
|---|
| 701 |
fmt.p_palette->palette[i][0] = i * 16 * i_y / 256; |
|---|
| 702 |
fmt.p_palette->palette[i][1] = i_u; |
|---|
| 703 |
fmt.p_palette->palette[i][2] = i_v; |
|---|
| 704 |
fmt.p_palette->palette[i][3] = pi_gamma[i]; |
|---|
| 705 |
fmt.p_palette->palette[i][3] = |
|---|
| 706 |
(int)fmt.p_palette->palette[i][3] * (255 - p_line->i_alpha) / 255; |
|---|
| 707 |
} |
|---|
| 708 |
|
|---|
| 709 |
p_dst = p_region->p_picture->Y_PIXELS; |
|---|
| 710 |
i_pitch = p_region->p_picture->Y_PITCH; |
|---|
| 711 |
|
|---|
| 712 |
|
|---|
| 713 |
memset( p_dst, 0, i_pitch * p_region->fmt.i_height ); |
|---|
| 714 |
|
|---|
| 715 |
for( ; p_line != NULL; p_line = p_line->p_next ) |
|---|
| 716 |
{ |
|---|
| 717 |
int i_glyph_tmax = 0; |
|---|
| 718 |
int i_bitmap_offset, i_offset, i_align_offset = 0; |
|---|
| 719 |
for( i = 0; p_line->pp_glyphs[i] != NULL; i++ ) |
|---|
| 720 |
{ |
|---|
| 721 |
FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ]; |
|---|
| 722 |
i_glyph_tmax = __MAX( i_glyph_tmax, p_glyph->top ); |
|---|
| 723 |
} |
|---|
| 724 |
|
|---|
| 725 |
if( p_line->i_width < i_width ) |
|---|
| 726 |
{ |
|---|
| 727 |
if( (p_region->i_align & 0x3) == SUBPICTURE_ALIGN_RIGHT ) |
|---|
| 728 |
{ |
|---|
| 729 |
i_align_offset = i_width - p_line->i_width; |
|---|
| 730 |
} |
|---|
| 731 |
else if( (p_region->i_align & 0x3) != SUBPICTURE_ALIGN_LEFT ) |
|---|
| 732 |
{ |
|---|
| 733 |
i_align_offset = ( i_width - p_line->i_width ) / 2; |
|---|
| 734 |
} |
|---|
| 735 |
} |
|---|
| 736 |
|
|---|
| 737 |
for( i = 0; p_line->pp_glyphs[i] != NULL; i++ ) |
|---|
| 738 |
{ |
|---|
| 739 |
FT_BitmapGlyph p_glyph = p_line->pp_glyphs[ i ]; |
|---|
| 740 |
|
|---|
| 741 |
i_offset = ( p_line->p_glyph_pos[ i ].y + |
|---|
| 742 |
i_glyph_tmax - p_glyph->top + 2 ) * |
|---|
| 743 |
i_pitch + p_line->p_glyph_pos[ i ].x + p_glyph->left + 2 + |
|---|
| 744 |
i_align_offset; |
|---|
| 745 |
|
|---|
| 746 |
for( y = 0, i_bitmap_offset = 0; y < p_glyph->bitmap.rows; y++ ) |
|---|
| 747 |
{ |
|---|
| 748 |
for( x = 0; x < p_glyph->bitmap.width; x++, i_bitmap_offset++ ) |
|---|
| 749 |
{ |
|---|
| 750 |
if( p_glyph->bitmap.buffer[i_bitmap_offset] ) |
|---|
| 751 |
p_dst[i_offset+x] = |
|---|
| 752 |
((int)p_glyph->bitmap.buffer[i_bitmap_offset] + 8)/16; |
|---|
| 753 |
} |
|---|
| 754 |
i_offset += i_pitch; |
|---|
| 755 |
} |
|---|
| 756 |
} |
|---|
| 757 |
} |
|---|
| 758 |
|
|---|
| 759 |
|
|---|
| 760 |
if( 1 ) |
|---|
| 761 |
{ |
|---|
| 762 |
uint8_t *p_dst = p_region->p_picture->Y_PIXELS; |
|---|
| 763 |
uint8_t *p_top = p_dst; |
|---|
| 764 |
uint8_t left, current; |
|---|
| 765 |
|
|---|
| 766 |
for( y = 1; y < (int)fmt.i_height - 1; y++ ) |
|---|
| 767 |
{ |
|---|
| 768 |
if( y > 1 ) memcpy( p_top, p_dst, fmt.i_width ); |
|---|
| 769 |
p_dst += p_region->p_picture->Y_PITCH; |
|---|
| 770 |
left = 0; |
|---|
| 771 |
|
|---|
| 772 |
for( x = 1; x < (int)fmt.i_width - 1; x++ ) |
|---|
| 773 |
{ |
|---|
| 774 |
current = p_dst[x]; |
|---|
| 775 |
p_dst[x] = ( 8 * (int)p_dst[x] + left + p_dst[x+1] + p_top[x -1]+ p_top[x] + p_top[x+1] + |
|---|
| 776 |
p_dst[x -1 + p_region->p_picture->Y_PITCH ] + p_dst[x + p_region->p_picture->Y_PITCH] + p_dst[x + 1 + p_region->p_picture->Y_PITCH]) / 16; |
|---|
| 777 |
left = current; |
|---|
| 778 |
} |
|---|
| 779 |
} |
|---|
| 780 |
memset( p_top, 0, fmt.i_width ); |
|---|
| 781 |
} |
|---|
| 782 |
|
|---|
| 783 |
return VLC_SUCCESS; |
|---|
| 784 |
} |
|---|
| 785 |
|
|---|
| 786 |
static void UnderlineGlyphYUVA( int i_line_thickness, int i_line_offset, bool b_ul_next_char, |
|---|
| 787 |
FT_BitmapGlyph p_this_glyph, FT_Vector *p_this_glyph_pos, |
|---|
| 788 |
FT_BitmapGlyph p_next_glyph, FT_Vector *p_next_glyph_pos, |
|---|
| 789 |
int i_glyph_tmax, int i_align_offset, |
|---|
| 790 |
uint8_t i_y, uint8_t i_u, uint8_t i_v, |
|---|
| 791 |
subpicture_region_t *p_region) |
|---|
| 792 |
{ |
|---|
| 793 |
int y, x, z; |
|---|
| 794 |
int i_pitch; |
|---|
| 795 |
uint8_t *p_dst_y,*p_dst_u,*p_dst_v,*p_dst_a; |
|---|
| 796 |
|
|---|
| 797 |
p_dst_y = p_region->p_picture->Y_PIXELS; |
|---|
| 798 |
p_dst_u = p_region->p_picture->U_PIXELS; |
|---|
| 799 |
p_dst_v = p_region->p_picture->V_PIXELS; |
|---|
| 800 |
p_dst_a = p_region->p_picture->A_PIXELS; |
|---|
| 801 |
i_pitch = p_region->p_picture->A_PITCH; |
|---|
| 802 |
|
|---|
| 803 |
int i_offset = ( p_this_glyph_pos->y + i_glyph_tmax + i_line_offset + 3 ) * i_pitch + |
|---|
| 804 |
p_this_glyph_pos->x + p_this_glyph->left + 3 + i_align_offset; |
|---|
| 805 |
|
|---|
| 806 |
for( y = 0; y < i_line_thickness; y++ ) |
|---|
| 807 |
{ |
|---|
| 808 |
int i_extra = p_this_glyph->bitmap.width; |
|---|
| 809 |
|
|---|
| 810 |
if( b_ul_next_char ) |
|---|
| 811 |
{ |
|---|
| 812 |
i_extra = (p_next_glyph_pos->x + p_next_glyph->left) - |
|---|
| 813 |
(p_this_glyph_pos->x + p_this_glyph->left); |
|---|
| 814 |
} |
|---|
| 815 |
for( x = 0; x < i_extra; x++ ) |
|---|
| 816 |
{ |
|---|
| 817 |
bool b_ok = true; |
|---|
| 818 |
|
|---|
| 819 |
|
|---|
| 820 |
for( z = x - i_line_thickness; |
|---|
| 821 |
z < x + i_line_thickness && b_ok; |
|---|
| 822 |
z++ ) |
|---|
| 823 |
{ |
|---|
| 824 |
if( p_next_glyph && ( z >= i_extra ) ) |
|---|
| 825 |
{ |
|---|
| 826 |
int i_row = i_line_offset + p_next_glyph->top + y; |
|---|
| 827 |
|
|---|
| 828 |
if( ( p_next_glyph->bitmap.rows > i_row ) && |
|---|
| 829 |
p_next_glyph->bitmap.buffer[p_next_glyph->bitmap.width * i_row + z-i_extra] ) |
|---|
| 830 |
{ |
|---|
| 831 |
b_ok = false; |
|---|
| 832 |
} |
|---|
| 833 |
} |
|---|
| 834 |
else if ((z > 0 ) && (z < p_this_glyph->bitmap.width)) |
|---|
| 835 |
{ |
|---|
| 836 |
int i_row = i_line_offset + p_this_glyph->top + y; |
|---|
| 837 |
|
|---|
| 838 |
if( ( p_this_glyph->bitmap.rows > i_row ) && |
|---|
| 839 |
p_this_glyph->bitmap.buffer[p_this_glyph->bitmap.width * i_row + z] ) |
|---|
| 840 |
{ |
|---|
| 841 |
b_ok = false; |
|---|
| 842 |
} |
|---|
| 843 |
} |
|---|
| 844 |
} |
|---|
| 845 |
|
|---|
| 846 |
if( b_ok ) |
|---|
| 847 |
{ |
|---|
| 848 |
p_dst_y[i_offset+x] = (i_y * 255) >> 8; |
|---|
| 849 |
p_dst_u[i_offset+x] = i_u; |
|---|
| 850 |
p_dst_v[i_offset+x] = i_v; |
|---|
| 851 |
p_dst_a[i_offset+x] = 255; |
|---|
| 852 |
} |
|---|
| 853 |
} |
|---|
| 854 |
i_offset += i_pitch; |
|---|
| 855 |
} |
|---|
| 856 |
} |
|---|
| 857 |
|
|---|
| 858 |
static void DrawBlack( line_desc_t *p_line, int i_width, subpicture_region_t *p_region, int xoffset, int yoffset ) |
|---|
| 859 |
{ |
|---|
| 860 |
uint8_t *p_dst = p_region->p_picture->A_PIXELS; |
|---|
| 861 |
int i_pitch = p_region->p_picture->A_PITCH; |
|---|
| 862 |
int x,y; |
|---|
| 863 |
|
|---|
| 864 |
for( ; p_line != NULL; p_line = p_line->p_next ) |
|---|
| 865 |
{ |
|---|
| 866 |
int i_glyph_tmax=0, i = 0; |
|---|
| 867 |
int i_bitmap_offset, i_offset, i_align_offset = 0; |
|---|
| 868 |
|
|---|