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
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;
|
|
}
|
|
}
|
|
}
|
|
|