[vlc-commits] codec: webvtt: fix regionless cues position

Francois Cartegnie git at videolan.org
Fri Jan 19 18:45:26 CET 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jan 19 16:18:48 2018 +0100| [8c861a3c4913da41fda7bab1980d445e93d03a5f] | committer: Francois Cartegnie

codec: webvtt: fix regionless cues position

somehow limited

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8c861a3c4913da41fda7bab1980d445e93d03a5f
---

 modules/codec/webvtt/subsvtt.c | 133 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 121 insertions(+), 12 deletions(-)

diff --git a/modules/codec/webvtt/subsvtt.c b/modules/codec/webvtt/subsvtt.c
index bb0cb60c34..d22d80d94a 100644
--- a/modules/codec/webvtt/subsvtt.c
+++ b/modules/codec/webvtt/subsvtt.c
@@ -86,7 +86,7 @@ typedef struct
     enum webvtt_align_e linealign;
     float position;
     enum webvtt_align_e positionalign;
-    float size;
+    webvtt_auto_value_t size;
     enum webvtt_align_e align;
 } webvtt_cue_settings_t;
 
@@ -203,6 +203,89 @@ static bool parse_percent_tuple( const char *psz, float *x, float *y )
     return false;
 }
 
+typedef struct
+{
+    float x,y,w,h;
+} webvtt_rect_t;
+
+static void webvtt_get_cueboxrect( const webvtt_cue_settings_t *p_settings,
+                                   webvtt_rect_t *p_rect )
+{
+    float extent;
+    float indent_anchor_position;
+    enum webvtt_align_e alignment_on_indent_anchor;
+
+    /* Position of top or left depending on writing direction */
+    float line_offset;
+    if( !p_settings->line.b_auto ) /* numerical */
+    {
+        if( p_settings->b_snap_to_lines ) /* line # */
+            line_offset = p_settings->line.value /
+                          (WEBVTT_REGION_LINES_COUNT * WEBVTT_LINE_TO_HEIGHT_RATIO);
+        else
+            line_offset = p_settings->line.value;
+    }
+    else line_offset = 1.0;
+
+    if( p_settings->position < 0 )
+    {
+        if( p_settings->align == WEBVTT_ALIGN_LEFT )
+            indent_anchor_position = 0;
+        else if( p_settings->align == WEBVTT_ALIGN_RIGHT )
+            indent_anchor_position = 1.0;
+        else
+            indent_anchor_position = 0.5; /* center */
+    }
+    else indent_anchor_position = p_settings->position;
+
+    if( p_settings->positionalign == WEBVTT_ALIGN_AUTO )
+    {
+        /* text align */
+        if( p_settings->align == WEBVTT_ALIGN_LEFT ||
+            p_settings->align == WEBVTT_ALIGN_RIGHT )
+            alignment_on_indent_anchor = p_settings->align;
+        else
+            alignment_on_indent_anchor = WEBVTT_ALIGN_CENTER;
+    }
+    else alignment_on_indent_anchor = p_settings->positionalign;
+
+    if( !p_settings->size.b_auto )
+        extent = p_settings->size.value;
+    else
+        extent = 0.0;
+
+    /* apply */
+
+    /* we need 100% or size for inner_align to work on writing direction */
+    if( p_settings->vertical == WEBVTT_ALIGN_AUTO ) /* Horizontal text */
+    {
+        p_rect->y = line_offset > 0 ? line_offset : 1.0 + line_offset;
+        p_rect->w = (extent) ? extent : 1.0;
+        if( indent_anchor_position > 0 &&
+            (alignment_on_indent_anchor == WEBVTT_ALIGN_LEFT ||
+             alignment_on_indent_anchor == WEBVTT_ALIGN_START) )
+        {
+            p_rect->x  = indent_anchor_position;
+            p_rect->w -= p_rect->x;
+        }
+    }
+    else /* Vertical text */
+    {
+        if( p_settings->vertical == WEBVTT_ALIGN_LEFT )
+            p_rect->x = line_offset > 0 ? 1.0 - line_offset : -line_offset;
+        else
+            p_rect->x = line_offset > 0 ? line_offset : 1.0 + line_offset;
+        p_rect->y = (extent) ? extent : 1.0;
+
+        if( indent_anchor_position > 0 &&
+            alignment_on_indent_anchor == WEBVTT_ALIGN_START )
+        {
+            p_rect->y  = indent_anchor_position;
+            p_rect->h -= p_rect->y;
+        }
+    }
+}
+
 static void webvtt_cue_settings_ParseTuple( webvtt_cue_settings_t *p_settings,
                                             const char *psz_key, const char *psz_value )
 {
@@ -217,6 +300,7 @@ static void webvtt_cue_settings_ParseTuple( webvtt_cue_settings_t *p_settings,
     }
     else if( !strcmp( psz_key, "line" ) )
     {
+        p_settings->line.b_auto = false;
         if( strchr( psz_value, '%' ) )
         {
             parse_percent( psz_value, &p_settings->line.value );
@@ -224,7 +308,6 @@ static void webvtt_cue_settings_ParseTuple( webvtt_cue_settings_t *p_settings,
         }
         else
             p_settings->line.value = us_strtof( psz_value, NULL );
-
         /* else auto */
 
         const char *psz_align = strchr( psz_value, ',' );
@@ -256,7 +339,8 @@ static void webvtt_cue_settings_ParseTuple( webvtt_cue_settings_t *p_settings,
     }
     else if( !strcmp( psz_key, "size" ) )
     {
-        parse_percent( psz_value, &p_settings->size );
+        parse_percent( psz_value, &p_settings->size.value );
+        p_settings->size.b_auto = false;
     }
     else if( !strcmp( psz_key, "region" ) )
     {
@@ -318,7 +402,8 @@ static void webvtt_cue_settings_Init( webvtt_cue_settings_t *p_settings )
     p_settings->linealign = WEBVTT_ALIGN_START;
     p_settings->position = -1;
     p_settings->positionalign = WEBVTT_ALIGN_AUTO;
-    p_settings->size = 1.0; /* 100% */
+    p_settings->size.value = 1.0; /* 100% */
+    p_settings->size.b_auto = true;
     p_settings->align = WEBVTT_ALIGN_CENTER;
 }
 
@@ -1658,21 +1743,45 @@ static void RenderRegions( decoder_t *p_dec, mtime_t i_start, mtime_t i_stop )
         v.i_top = 0.0;
         /* !Variables */
 
-        text_segment_t *p_segments = ConvertCuesToSegments( p_dec, i_start, i_stop, &v, p_rlcue );
-        if( p_segments )
+        for( const webvtt_dom_cue_t *p_cue = p_rlcue; p_cue;
+             p_cue = (const webvtt_dom_cue_t *) p_cue->p_next )
         {
+            if( p_cue->type != NODE_CUE )
+                continue;
+
+            if( p_cue->i_start > i_start || p_cue->i_stop <= i_start )
+                continue;
+
+            text_segment_t *p_segments = ConvertCueToSegments( p_dec, &v, p_cue );
+            if( !p_segments )
+                continue;
+
             CreateSpuOrNewUpdaterRegion( p_dec, &p_spu, &p_updtregion );
-            if( !p_spu || !p_updtregion )
+            if( !p_updtregion )
             {
                 text_segment_ChainDelete( p_segments );
+                continue;
             }
-            else
+
+            if( p_cue->settings.line.b_auto )
             {
                 p_updtregion->align = SUBPICTURE_ALIGN_BOTTOM;
-                p_updtregion->inner_align = GetCueTextAlignment( p_rlcue );
-
-                p_updtregion->p_segments = p_segments;
             }
+            else
+            {
+                webvtt_rect_t rect = { 0,0,0,0 };
+                webvtt_get_cueboxrect( &p_cue->settings, &rect );
+                p_updtregion->align = SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_LEFT;
+                p_updtregion->origin.x = rect.x;
+                p_updtregion->origin.y = rect.y;
+                p_updtregion->extent.x = rect.w;
+                p_updtregion->extent.y = rect.h;
+                p_updtregion->flags |= (UPDT_REGION_ORIGIN_X_IS_RATIO|UPDT_REGION_ORIGIN_Y_IS_RATIO|
+                                        UPDT_REGION_EXTENT_X_IS_RATIO|UPDT_REGION_EXTENT_Y_IS_RATIO);
+            }
+
+            p_updtregion->inner_align = GetCueTextAlignment( p_cue );
+            p_updtregion->p_segments = p_segments;
         }
     }
 
@@ -1681,7 +1790,7 @@ static void RenderRegions( decoder_t *p_dec, mtime_t i_start, mtime_t i_stop )
         p_spu->i_start = i_start;
         p_spu->i_stop = i_stop;
         p_spu->b_ephemer  = true; /* !important */
-        p_spu->b_absolute = false;
+        p_spu->b_absolute = false; /* can't be absolute as snap to lines can overlap ! */
 
         subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
         p_spu_sys->p_default_style->f_font_relsize = WEBVTT_DEFAULT_LINE_HEIGHT_VH /



More information about the vlc-commits mailing list