You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

274 lines
9.6 KiB

/*****************************************************************************
* css_style.c : CSS styles conversions
*****************************************************************************
* Copyright (C) 2017 VideoLabs, VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_text_style.h>
#include "css_parser.h"
#include "css_style.h"
static void Color( vlc_css_term_t term,
uint32_t *color, uint8_t *alpha,
uint16_t *feat, int cflag, int aflag )
{
if( term.type == TYPE_FUNCTION )
{
if( term.function ) /* func( expr ) */
{
if( ( !strcmp( term.psz, "rgb" ) && term.function->i_count == 3 ) ||
( !strcmp( term.psz, "rgba" ) && term.function->i_count == 4 ) )
{
*color = (((uint32_t)term.function->seq[0].term.val) << 16) |
(((uint32_t)term.function->seq[1].term.val) << 8) |
((uint32_t)term.function->seq[2].term.val);
*feat |= cflag;
if( term.psz[3] != 0 ) /* rgba */
{
*alpha = term.function->seq[3].term.val * STYLE_ALPHA_OPAQUE;
*feat |= aflag;
}
}
}
}
else if( term.type == TYPE_STRING ||
term.type == TYPE_HEXCOLOR ||
term.type == TYPE_IDENTIFIER )
{
bool b_valid = false;
unsigned i_color = vlc_html_color( term.psz, &b_valid );
if( b_valid )
{
*alpha = (i_color & 0xFF000000) >> 24;
*color = i_color & 0x00FFFFFF;
*feat |= cflag|aflag;
}
}
}
static void OutlineWidth( vlc_css_term_t term, text_style_t *p_style )
{
if( term.type >= TYPE_PIXELS )
{
p_style->i_outline_width = term.val;
p_style->i_style_flags |= STYLE_OUTLINE;
p_style->i_features |= STYLE_HAS_FLAGS;
}
}
static void OutlineColor( vlc_css_term_t term, text_style_t *p_style )
{
Color( term, &p_style->i_outline_color, &p_style->i_outline_alpha,
&p_style->i_features, STYLE_HAS_OUTLINE_COLOR, STYLE_HAS_OUTLINE_ALPHA );
}
static void ShadowDrop( vlc_css_term_t term, text_style_t *p_style )
{
if( term.type >= TYPE_PIXELS )
{
p_style->i_shadow_width = term.val;
p_style->i_style_flags |= STYLE_SHADOW;
p_style->i_features |= STYLE_HAS_FLAGS;
}
}
static void ShadowColor( vlc_css_term_t term, text_style_t *p_style )
{
Color( term, &p_style->i_shadow_color, &p_style->i_shadow_alpha,
&p_style->i_features, STYLE_HAS_SHADOW_COLOR, STYLE_HAS_SHADOW_ALPHA );
}
void webvtt_FillStyleFromCssDeclaration( const vlc_css_declaration_t *p_decl, text_style_t *p_style )
{
if( !p_decl->psz_property || !p_style )
return;
/* Only support simple expressions for now */
if( p_decl->expr->i_count < 1 )
return;
vlc_css_term_t term0 = p_decl->expr->seq[0].term;
if( !strcasecmp( p_decl->psz_property, "color" ) )
{
Color( term0, &p_style->i_font_color, &p_style->i_font_alpha,
&p_style->i_features, STYLE_HAS_FONT_COLOR, STYLE_HAS_FONT_ALPHA );
}
else if( !strcasecmp( p_decl->psz_property, "text-decoration" ) )
{
if( term0.type == TYPE_STRING )
{
if( !strcasecmp( term0.psz, "none" ) )
{
p_style->i_style_flags &= ~(STYLE_STRIKEOUT|STYLE_UNDERLINE);
p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( term0.psz, "line-through" ) )
{
p_style->i_style_flags |= STYLE_STRIKEOUT;
p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( term0.psz, "underline" ) )
{
p_style->i_style_flags |= STYLE_UNDERLINE;
p_style->i_features |= STYLE_HAS_FLAGS;
}
}
}
else if( !strcasecmp( p_decl->psz_property, "text-shadow" ) )
{
ShadowDrop( term0, p_style );
if( p_decl->expr->i_count == 3 )
ShadowColor( p_decl->expr->seq[2].term, p_style );
}
else if( !strcasecmp( p_decl->psz_property, "background-color" ) )
{
Color( term0, &p_style->i_background_color, &p_style->i_background_alpha,
&p_style->i_features, STYLE_HAS_BACKGROUND_COLOR, STYLE_HAS_BACKGROUND_ALPHA );
p_style->i_style_flags |= STYLE_BACKGROUND;
p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp( p_decl->psz_property, "outline-color" ) )
{
OutlineColor( term0, p_style );
}
else if( !strcasecmp( p_decl->psz_property, "outline-width" ) )
{
OutlineWidth( term0, p_style );
}
else if( !strcasecmp( p_decl->psz_property, "outline" ) )
{
OutlineWidth( term0, p_style );
if( p_decl->expr->i_count == 3 )
OutlineColor( p_decl->expr->seq[2].term, p_style );
}
else if( !strcasecmp( p_decl->psz_property, "font-family" ) )
{
vlc_css_term_t *term;
if( term0.type >= TYPE_STRING )
{
size_t i_total = 1 + (p_decl->expr->i_count - 1) * 2;
for( size_t i=0; i<p_decl->expr->i_count; i++ )
{
term = &p_decl->expr->seq[i].term;
if( term->type < TYPE_STRING )
continue;
i_total += strlen( term->psz );
if( term->type == TYPE_STRING )
i_total += 2;
}
char *psz = malloc( i_total );
if( psz )
{
*psz = 0;
for( size_t i=0; i<p_decl->expr->i_count; i++ )
{
term = &p_decl->expr->seq[i].term;
if( term->type < TYPE_STRING )
continue;
if( i > 0 )
strcat( psz, ", " );
i_total += strlen( term->psz );
if( term->type == TYPE_STRING )
strcat( psz, "\"" );
strcat( psz, term->psz );
if( term->type == TYPE_STRING )
strcat( psz, "\"" );
}
free( p_style->psz_fontname );
p_style->psz_fontname = psz;
}
/*char *psz_font = NULL;
const char *psz = strchr( term0.psz, ',' );
if( psz )
psz_font = strndup( term0.psz, psz - term0.psz + 1 );
else
psz_font = strdup( term0.psz );
free( p_style->psz_fontname );
p_style->psz_fontname = vlc_css_unquoted( psz_font );
free( psz_font );*/
}
}
else if( !strcasecmp( p_decl->psz_property, "font-style" ) )
{
if( term0.type >= TYPE_STRING )
{
if( !strcasecmp(term0.psz, "normal") )
{
p_style->i_style_flags &= ~STYLE_ITALIC;
p_style->i_features |= STYLE_HAS_FLAGS;
}
else if( !strcasecmp(term0.psz, "italic") )
{
p_style->i_style_flags |= STYLE_ITALIC;
p_style->i_features |= STYLE_HAS_FLAGS;
}
}
}
else if( !strcasecmp( p_decl->psz_property, "font-weight" ) )
{
if( term0.type >= TYPE_STRING )
{
if( !strcasecmp(term0.psz, "normal") )
{
p_style->i_style_flags &= ~STYLE_BOLD;
p_style->i_features |= STYLE_HAS_FLAGS;
}
if( !strcasecmp(term0.psz, "bold") )
{
p_style->i_style_flags |= STYLE_BOLD;
p_style->i_features |= STYLE_HAS_FLAGS;
}
}
else if( term0.type == TYPE_NONE )
{
if( term0.val >= 700.0 )
p_style->i_style_flags |= STYLE_BOLD;
else
p_style->i_style_flags &= ~STYLE_BOLD;
p_style->i_features |= STYLE_HAS_FLAGS;
}
}
else if( !strcasecmp( p_decl->psz_property, "font-size" ) )
{
if( term0.type == TYPE_PIXELS )
p_style->i_font_size = term0.val;
else if( term0.type == TYPE_EMS )
p_style->f_font_relsize = term0.val * 5.33 / 1.06;
else if( term0.type == TYPE_PERCENT )
p_style->f_font_relsize = term0.val * 5.33 / 100;
}
else if( !strcasecmp( p_decl->psz_property, "font" ) )
{
/* what to do ? */
}
else if( !strcasecmp( p_decl->psz_property, "white-space" ) )
{
if( term0.type >= TYPE_STRING )
{
if( !strcasecmp(term0.psz, "normal" ) )
p_style->e_wrapinfo = STYLE_WRAP_DEFAULT;
if( !strcasecmp(term0.psz, "nowrap" ) )
p_style->e_wrapinfo = STYLE_WRAP_NONE;
}
}
}