1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 1999-2010 VLC authors and VideoLAN
7 * Author: basOS G <noxelia 4t gmail , com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_text_style.h>
34 text_style_t
*text_style_New( void )
36 return text_style_Create( STYLE_FULLY_SET
);
39 text_style_t
*text_style_Create( int i_defaults
)
41 text_style_t
*p_style
= calloc( 1, sizeof(*p_style
) );
45 if( i_defaults
== STYLE_NO_DEFAULTS
)
48 /* initialize to default text style (FIXME: by flag) */
49 p_style
->psz_fontname
= NULL
;
50 p_style
->psz_monofontname
= NULL
;
51 p_style
->i_features
= STYLE_FULLY_SET
;
52 p_style
->i_style_flags
= STYLE_OUTLINE
;
53 p_style
->f_font_relsize
= STYLE_DEFAULT_REL_FONT_SIZE
;
54 p_style
->i_font_size
= STYLE_DEFAULT_FONT_SIZE
;
55 p_style
->i_font_color
= 0xffffff;
56 p_style
->i_font_alpha
= STYLE_ALPHA_OPAQUE
;
57 p_style
->i_outline_color
= 0x000000;
58 p_style
->i_outline_alpha
= STYLE_ALPHA_OPAQUE
;
59 p_style
->i_shadow_color
= 0x808080;
60 p_style
->i_shadow_alpha
= STYLE_ALPHA_OPAQUE
;
61 p_style
->i_background_color
= 0x000000;
62 p_style
->i_background_alpha
= STYLE_ALPHA_OPAQUE
;
63 p_style
->i_karaoke_background_color
= 0xffffff;
64 p_style
->i_karaoke_background_alpha
= STYLE_ALPHA_OPAQUE
;
65 p_style
->i_outline_width
= 1;
66 p_style
->i_shadow_width
= 0;
67 p_style
->i_spacing
= -1;
68 p_style
->e_wrapinfo
= STYLE_WRAP_DEFAULT
;
73 text_style_t
*text_style_Copy( text_style_t
*p_dst
, const text_style_t
*p_src
)
81 if( p_src
->psz_fontname
)
82 p_dst
->psz_fontname
= strdup( p_src
->psz_fontname
);
84 if( p_src
->psz_monofontname
)
85 p_dst
->psz_monofontname
= strdup( p_src
->psz_monofontname
);
90 #define MERGE(var, fflag) \
91 if( (p_src->i_features & fflag) && (b_override || !(p_dst->i_features & fflag)) )\
92 p_dst->var = p_src->var
94 #define MERGE_SIZE(var) \
95 if( p_src->var > 0 && (b_override || p_dst->var <= 0) )\
96 p_dst->var = p_src->var
98 void text_style_Merge( text_style_t
*p_dst
, const text_style_t
*p_src
, bool b_override
)
100 if( p_src
->psz_fontname
&& (!p_dst
->psz_fontname
|| b_override
) )
102 free( p_dst
->psz_fontname
);
103 p_dst
->psz_fontname
= strdup( p_src
->psz_fontname
);
106 if( p_src
->psz_monofontname
&& (!p_dst
->psz_monofontname
|| b_override
) )
108 free( p_dst
->psz_monofontname
);
109 p_dst
->psz_monofontname
= strdup( p_src
->psz_monofontname
);
112 if( p_src
->i_features
!= STYLE_NO_DEFAULTS
)
114 MERGE(i_font_color
, STYLE_HAS_FONT_COLOR
);
115 MERGE(i_font_alpha
, STYLE_HAS_FONT_ALPHA
);
116 MERGE(i_outline_color
, STYLE_HAS_OUTLINE_COLOR
);
117 MERGE(i_outline_alpha
, STYLE_HAS_OUTLINE_ALPHA
);
118 MERGE(i_shadow_color
, STYLE_HAS_SHADOW_COLOR
);
119 MERGE(i_shadow_alpha
, STYLE_HAS_SHADOW_ALPHA
);
120 MERGE(i_background_color
, STYLE_HAS_BACKGROUND_COLOR
);
121 MERGE(i_background_alpha
, STYLE_HAS_BACKGROUND_ALPHA
);
122 MERGE(i_karaoke_background_color
, STYLE_HAS_K_BACKGROUND_COLOR
);
123 MERGE(i_karaoke_background_alpha
, STYLE_HAS_K_BACKGROUND_ALPHA
);
124 MERGE(e_wrapinfo
, STYLE_HAS_WRAP_INFO
);
125 p_dst
->i_features
|= p_src
->i_features
;
126 p_dst
->i_style_flags
|= p_src
->i_style_flags
;
129 MERGE_SIZE(f_font_relsize
);
130 MERGE_SIZE(i_font_size
);
131 MERGE_SIZE(i_outline_width
);
132 MERGE_SIZE(i_shadow_width
);
133 MERGE_SIZE(i_spacing
);
139 text_style_t
*text_style_Duplicate( const text_style_t
*p_src
)
144 text_style_t
*p_dst
= calloc( 1, sizeof(*p_dst
) );
146 text_style_Copy( p_dst
, p_src
);
150 void text_style_Delete( text_style_t
*p_style
)
153 free( p_style
->psz_fontname
);
155 free( p_style
->psz_monofontname
);
159 void text_segment_ruby_ChainDelete( text_segment_ruby_t
*p_ruby
)
163 text_segment_ruby_t
*p_next
= p_ruby
->p_next
;
164 free( p_ruby
->psz_base
);
165 free( p_ruby
->psz_rt
);
171 text_segment_ruby_t
*text_segment_ruby_New( const char *psz_base
,
174 text_segment_ruby_t
*p_rb
= malloc(sizeof(*p_rb
));
178 p_rb
->psz_base
= strdup( psz_base
);
179 p_rb
->psz_rt
= strdup( psz_rt
);
180 if( !p_rb
->psz_base
|| !p_rb
->psz_rt
)
182 text_segment_ruby_ChainDelete( p_rb
);
189 static text_segment_ruby_t
*text_segment_ruby_Duplicate( const text_segment_ruby_t
*p_src
)
191 text_segment_ruby_t
*p_dup
= NULL
;
192 text_segment_ruby_t
**pp_append
= &p_dup
;
193 for ( ; p_src
; p_src
= p_src
->p_next
)
195 *pp_append
= text_segment_ruby_New( p_src
->psz_base
, p_src
->psz_rt
);
197 pp_append
= &((*pp_append
)->p_next
);
202 text_segment_t
*text_segment_New( const char *psz_text
)
204 text_segment_t
* segment
= calloc( 1, sizeof(*segment
) );
209 segment
->psz_text
= strdup( psz_text
);
214 text_segment_t
*text_segment_NewInheritStyle( const text_style_t
* p_style
)
217 return NULL
; //FIXME: Allow this, even if it is an alias to text_segment_New( NULL ) ?
218 text_segment_t
* p_segment
= text_segment_New( NULL
);
219 if ( unlikely( !p_segment
) )
221 p_segment
->style
= text_style_Duplicate( p_style
);
222 if ( unlikely( !p_segment
->style
) )
224 text_segment_Delete( p_segment
);
230 text_segment_t
*text_segment_FromRuby( text_segment_ruby_t
*p_ruby
)
232 text_segment_t
*p_segment
= text_segment_New( NULL
);
235 p_segment
->p_ruby
= p_ruby
;
237 for( text_segment_ruby_t
*p
= p_ruby
; p
; p
= p
->p_next
)
238 i_base
+= strlen( p
->psz_base
);
239 p_segment
->psz_text
= malloc( i_base
);
240 /* Fallback for those not understanding p_ruby */
241 if( p_segment
->psz_text
)
243 *p_segment
->psz_text
= 0;
244 for( text_segment_ruby_t
*p
= p_ruby
; p
; p
= p
->p_next
)
245 strcat( p_segment
->psz_text
, p
->psz_base
);
251 void text_segment_Delete( text_segment_t
* segment
)
253 if ( segment
!= NULL
)
255 free( segment
->psz_text
);
256 text_style_Delete( segment
->style
);
257 text_segment_ruby_ChainDelete( segment
->p_ruby
);
262 void text_segment_ChainDelete( text_segment_t
*segment
)
264 while( segment
!= NULL
)
266 text_segment_t
*p_next
= segment
->p_next
;
268 text_segment_Delete( segment
);
274 text_segment_t
*text_segment_Copy( text_segment_t
*p_src
)
276 text_segment_t
*p_dst
= NULL
, *p_dst0
= NULL
;
279 text_segment_t
*p_new
= text_segment_New( p_src
->psz_text
);
281 if( unlikely( !p_new
) )
284 p_new
->style
= text_style_Duplicate( p_src
->style
);
285 p_new
->p_ruby
= text_segment_ruby_Duplicate( p_src
->p_ruby
);
289 p_dst
= p_dst0
= p_new
;
293 p_dst
->p_next
= p_new
;
294 p_dst
= p_dst
->p_next
;
297 p_src
= p_src
->p_next
;
303 unsigned int vlc_html_color( const char *psz_value
, bool* ok
)
305 unsigned int color
= 0;
309 const char *psz_hex
= (*psz_value
== '#') ? psz_value
+ 1 : psz_value
;
311 if( psz_hex
!= psz_value
||
312 (*psz_hex
>= '0' && *psz_hex
<= '9') ||
313 (*psz_hex
>= 'A' && *psz_hex
<= 'F') )
315 uint32_t i_value
= (uint32_t)strtoul( psz_hex
, &psz_end
, 16 );
316 if( *psz_end
== 0 || isspace( *psz_end
) )
318 switch( psz_end
- psz_hex
)
321 color
= (i_value
<< 24) | (i_value
>> 8);
325 color
= i_value
| 0xFF000000;
334 if( !b_ret
&& psz_hex
== psz_value
&&
335 !strncmp( "rgb", psz_value
, 3 ) )
337 unsigned r
,g
,b
,a
= 0xFF;
338 if( psz_value
[3] == 'a' )
339 b_ret
= (sscanf( psz_value
, "rgba(%3u,%3u,%3u,%3u)", &r
, &g
, &b
, &a
) == 4);
341 b_ret
= (sscanf( psz_value
, "rgb(%3u,%3u,%3u)", &r
, &g
, &b
) == 3);
342 color
= (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
345 if( !b_ret
&& psz_hex
== psz_value
)
347 for( int i
= 0; p_html_colors
[i
].psz_name
!= NULL
; i
++ )
349 if( !strcasecmp( psz_value
, p_html_colors
[i
].psz_name
) )
351 // Assume opaque color since the table doesn't specify an alpha
352 color
= p_html_colors
[i
].i_value
| 0xFF000000;