[vlc-commits] text_renderer: freetype: rework bounding

Francois Cartegnie git at videolan.org
Mon Oct 23 14:48:17 CEST 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sun Oct 22 19:28:21 2017 +0200| [f17a250a25cb26446909649569437d2b301157fb] | committer: Francois Cartegnie

text_renderer: freetype: rework bounding

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

 modules/text_renderer/freetype/freetype.c | 138 ++++++++++++++----------------
 1 file changed, 64 insertions(+), 74 deletions(-)

diff --git a/modules/text_renderer/freetype/freetype.c b/modules/text_renderer/freetype/freetype.c
index 32a1da3e26..13cc2a79b4 100644
--- a/modules/text_renderer/freetype/freetype.c
+++ b/modules/text_renderer/freetype/freetype.c
@@ -268,6 +268,24 @@ static void RGBFromRGB( uint32_t i_argb,
     *pi_b = ( i_argb & 0x000000ff );
 }
 
+static FT_Vector GetAlignedOffset( const line_desc_t *p_line,
+                                   const FT_BBox *p_textbbox,
+                                   int i_align )
+{
+    FT_Vector offsets = { 0, 0 };
+    const int i_text_width = p_textbbox->xMax - p_textbbox->xMin;
+    if ( p_line->i_width < i_text_width &&
+        (i_align & (SUBPICTURE_ALIGN_LEFT|SUBPICTURE_ALIGN_LEAVETEXT)) == 0 )
+    {
+        /* Left offset to take into account alignment */
+        if( i_align & SUBPICTURE_ALIGN_RIGHT )
+            offsets.x = ( i_text_width - p_line->i_width );
+        else /* center */
+            offsets.x = ( i_text_width - p_line->i_width ) / 2;
+    }
+    return offsets;
+}
+
 /*****************************************************************************
  * Make any TTF/OTF fonts present in the attachments of the media file
  * and store them for later use by the FreeType Engine
@@ -405,7 +423,7 @@ error:
  *****************************************************************************/
 static int RenderYUVP( filter_t *p_filter, subpicture_region_t *p_region,
                        line_desc_t *p_line,
-                       FT_BBox *p_bbox )
+                       FT_BBox *p_regionbbox, FT_BBox *p_bbox )
 {
     VLC_UNUSED(p_filter);
     static const uint8_t pi_gamma[16] =
@@ -421,9 +439,9 @@ static int RenderYUVP( filter_t *p_filter, subpicture_region_t *p_region,
     /* Create a new subpicture region */
     video_format_Init( &fmt, VLC_CODEC_YUVP );
     fmt.i_width          =
-    fmt.i_visible_width  = p_bbox->xMax - p_bbox->xMin + 4;
+    fmt.i_visible_width  = p_regionbbox->xMax - p_regionbbox->xMin + 4;
     fmt.i_height         =
-    fmt.i_visible_height = p_bbox->yMax - p_bbox->yMin + 4;
+    fmt.i_visible_height = p_regionbbox->yMax - p_regionbbox->yMin + 4;
     const unsigned regionnum = p_region->fmt.i_sar_num;
     const unsigned regionden = p_region->fmt.i_sar_den;
     fmt.i_sar_num = fmt.i_sar_den = 1;
@@ -471,23 +489,15 @@ static int RenderYUVP( filter_t *p_filter, subpicture_region_t *p_region,
 
     for( ; p_line != NULL; p_line = p_line->p_next )
     {
-        int i_align_left = 0;
-        if( p_line->i_width < (int)fmt.i_visible_width )
-        {
-            if( (p_region->i_align & 0x3) == SUBPICTURE_ALIGN_RIGHT )
-                i_align_left = ( fmt.i_visible_width - p_line->i_width );
-            else if( (p_region->i_align & 0x3) != SUBPICTURE_ALIGN_LEFT )
-                i_align_left = ( fmt.i_visible_width - p_line->i_width ) / 2;
-        }
-        int i_align_top = 0;
+        FT_Vector offset = GetAlignedOffset( p_line, p_bbox, p_region->i_align );
 
         for( i = 0; i < p_line->i_character_count; i++ )
         {
             const line_character_t *ch = &p_line->p_character[i];
             FT_BitmapGlyph p_glyph = ch->p_glyph;
 
-            int i_glyph_y = i_align_top  - p_glyph->top  + p_bbox->yMax + p_line->i_base_line;
-            int i_glyph_x = i_align_left + p_glyph->left - p_bbox->xMin;
+            int i_glyph_y = offset.y + p_regionbbox->yMax - p_glyph->top + p_line->i_base_line;
+            int i_glyph_x = offset.x + p_glyph->left - p_regionbbox->xMin;
 
             for( y = 0; y < p_glyph->bitmap.rows; y++ )
             {
@@ -710,52 +720,36 @@ static inline void BlendAXYZLine( picture_t *p_picture,
 
 static inline void RenderBackground( subpicture_region_t *p_region,
                                      line_desc_t *p_line_head,
-                                     FT_BBox *p_bbox,
-                                     int i_margin,
+                                     FT_BBox *p_regionbbox,
+                                     FT_BBox *p_textbbox,
                                      picture_t *p_picture,
-                                     int i_text_width,
                                      void (*ExtractComponents)( uint32_t, uint8_t *, uint8_t *, uint8_t * ),
                                      void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) )
 {
-    for( line_desc_t *p_line = p_line_head; p_line != NULL; p_line = p_line->p_next )
+    for( const line_desc_t *p_line = p_line_head; p_line != NULL; p_line = p_line->p_next )
     {
-        int i_align_left = i_margin;
-        int i_align_top = i_margin;
-        unsigned line_top = 0;
-        int line_bottom = 0;
-        int max_height = 0;
-
-        if( p_line->i_width < i_text_width )
-        {
-            /* Left offset to take into account alignment */
-            if( (p_region->i_align & 0x3) == SUBPICTURE_ALIGN_RIGHT )
-                i_align_left += ( i_text_width - p_line->i_width );
-            else if( (p_region->i_align & 0x10) == SUBPICTURE_ALIGN_LEAVETEXT)
-                i_align_left = i_margin; /* Keep it the way it is */
-            else if( (p_region->i_align & 0x3) != SUBPICTURE_ALIGN_LEFT )
-                i_align_left += ( i_text_width - p_line->i_width ) / 2;
-        }
-
-        /* Find the tallest character in the line */
-        for( int i = 0; i < p_line->i_character_count; i++ ) {
-            const line_character_t *ch = &p_line->p_character[i];
-            FT_BitmapGlyph p_glyph = ch->p_outline ? ch->p_outline : ch->p_glyph;
-            if (p_glyph->top > max_height)
-                max_height = p_glyph->top;
-        }
+        FT_Vector offset = GetAlignedOffset( p_line, p_textbbox, p_region->i_text_align );
 
         if( p_line->i_first_visible_char_index < 0 )
             continue; /* only spaces */
 
         /* Compute the upper boundary for the background */
-        line_top = __MAX(0, i_align_top - max_height  + p_bbox->yMax + p_line->i_base_line);
+        int line_top = __MAX(0, offset.y + p_regionbbox->yMax - p_line->bbox.yMax);
 
         /* Compute lower boundary for the background */
-        line_bottom =  __MIN(line_top + p_line->i_height, p_region->fmt.i_visible_height);
+        int line_bottom;
+        if( p_line->p_next == NULL || p_line->p_next->i_first_visible_char_index < 0 )
+        {
+            line_bottom = __MIN(p_region->fmt.i_visible_height, offset.y + p_regionbbox->yMax - p_line->bbox.yMin);
+        }
+        else
+        {
+            const int next_top = __MAX(0, offset.y + p_regionbbox->yMax - p_line->p_next->bbox.yMax);
+            line_bottom = __MIN(p_region->fmt.i_visible_height, next_top);
+        }
 
         /* Compute the background for the line (identify leading/trailing space) */
-        int line_start = p_line->p_character[p_line->i_first_visible_char_index].p_glyph->left +
-                         i_align_left - p_bbox->xMin;
+        int line_start = offset.x + p_line->p_character[p_line->i_first_visible_char_index].p_glyph->left - p_regionbbox->xMin;
 
         /* Fudge factor to make sure caption background edges are left aligned
            despite variable font width */
@@ -777,9 +771,9 @@ static inline void RenderBackground( subpicture_region_t *p_region,
             }
 
             /* Find right boundary for bounding box for background */
-            int line_end = p_line->p_character[i_seg_end].p_glyph->left +
-                           p_line->p_character[i_seg_end].p_glyph->bitmap.width +
-                           i_align_left - p_bbox->xMin;
+            int line_end = offset.x +
+                           p_line->p_character[i_seg_end].p_glyph->left - p_regionbbox->xMin +
+                           p_line->p_character[i_seg_end].p_glyph->bitmap.width;
 
             const line_character_t *p_char = &p_line->p_character[i_char_index];
             if( p_char->p_style->i_style_flags & STYLE_BACKGROUND )
@@ -813,22 +807,20 @@ static inline void RenderBackground( subpicture_region_t *p_region,
 static inline int RenderAXYZ( filter_t *p_filter,
                               subpicture_region_t *p_region,
                               line_desc_t *p_line_head,
-                              FT_BBox *p_bbox,
-                              int i_margin,
+                              FT_BBox *p_regionbbox,
+                              FT_BBox *p_textbbox,
                               vlc_fourcc_t i_chroma,
                               void (*ExtractComponents)( uint32_t, uint8_t *, uint8_t *, uint8_t * ),
                               void (*FillPicture)( picture_t *p_picture, int, int, int, int ),
                               void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) )
 {
     /* Create a new subpicture region */
-    const int i_text_width  = p_bbox->xMax - p_bbox->xMin;
-    const int i_text_height = p_bbox->yMax - p_bbox->yMin;
     video_format_t fmt;
     video_format_Init( &fmt, i_chroma );
     fmt.i_width          =
-    fmt.i_visible_width  = i_text_width  + 2 * i_margin;
+    fmt.i_visible_width  = p_regionbbox->xMax - p_regionbbox->xMin;
     fmt.i_height         =
-    fmt.i_visible_height = i_text_height + 2 * i_margin;
+    fmt.i_visible_height = p_regionbbox->yMax - p_regionbbox->yMin;
     const unsigned regionnum = p_region->fmt.i_sar_num;
     const unsigned regionden = p_region->fmt.i_sar_den;
     fmt.i_sar_num = fmt.i_sar_den = 1;
@@ -853,8 +845,9 @@ static inline int RenderAXYZ( filter_t *p_filter,
         ExtractComponents( p_style->i_background_color, &i_x, &i_y, &i_z );
         FillPicture( p_picture, p_style->i_background_alpha, i_x, i_y, i_z );
     }
+
     /* Render text's background (from decoder) if any */
-    RenderBackground(p_region, p_line_head, p_bbox, i_margin, p_picture, i_text_width,
+    RenderBackground(p_region, p_line_head, p_regionbbox, p_textbbox, p_picture,
                      ExtractComponents, BlendPixel);
 
     /* Render shadow then outline and then normal glyphs */
@@ -863,17 +856,7 @@ static inline int RenderAXYZ( filter_t *p_filter,
         /* Render all lines */
         for( line_desc_t *p_line = p_line_head; p_line != NULL; p_line = p_line->p_next )
         {
-            int i_align_left = i_margin;
-            if( p_line->i_width < i_text_width &&
-               (p_region->i_align & (SUBPICTURE_ALIGN_LEAVETEXT|SUBPICTURE_ALIGN_LEFT)) == 0 )
-            {
-                /* Left offset to take into account alignment */
-                if( p_region->i_align & SUBPICTURE_ALIGN_RIGHT )
-                    i_align_left += ( i_text_width - p_line->i_width );
-                else /* center */
-                    i_align_left += ( i_text_width - p_line->i_width ) / 2;
-            }
-            int i_align_top = i_margin;
+            FT_Vector offset = GetAlignedOffset( p_line, p_textbbox, p_region->i_align );
 
             /* Render all glyphs and underline/strikethrough */
             for( int i = p_line->i_first_visible_char_index; i <= p_line->i_last_visible_char_index; i++ )
@@ -909,8 +892,8 @@ static inline int RenderAXYZ( filter_t *p_filter,
 
                 ExtractComponents( i_color, &i_x, &i_y, &i_z );
 
-                int i_glyph_y = i_align_top  - p_glyph->top  + p_bbox->yMax + p_line->i_base_line;
-                int i_glyph_x = i_align_left + p_glyph->left - p_bbox->xMin;
+                int i_glyph_y = offset.y + p_regionbbox->yMax - p_glyph->top + p_line->i_base_line;
+                int i_glyph_x = offset.x + p_glyph->left - p_regionbbox->xMin;
 
                 BlendAXYZGlyph( p_picture,
                                 i_glyph_x, i_glyph_y,
@@ -1165,26 +1148,33 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
 
         uint8_t i_background_opacity = var_InheritInteger( p_filter, "freetype-background-opacity" );
         i_background_opacity = VLC_CLIP( i_background_opacity, 0, 255 );
-        const int i_margin = (i_background_opacity > 0 && !p_region_in->b_gridmode) ? i_max_face_height / 4 : 0;
+        int i_margin = (i_background_opacity > 0 && !p_region_in->b_gridmode) ? i_max_face_height / 4 : 0;
+
+        FT_BBox regionbbox = bbox;
+        regionbbox.xMin -= i_margin;
+        regionbbox.xMax += i_margin;
+        regionbbox.yMin -= i_margin;
+        regionbbox.yMax += i_margin;
+
         for( const vlc_fourcc_t *p_chroma = p_chroma_list; *p_chroma != 0; p_chroma++ )
         {
             rv = VLC_EGENERIC;
             if( *p_chroma == VLC_CODEC_YUVP )
-                rv = RenderYUVP( p_filter, p_region_out, p_lines, &bbox );
+                rv = RenderYUVP( p_filter, p_region_out, p_lines, &regionbbox, &bbox );
             else if( *p_chroma == VLC_CODEC_YUVA )
-                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &bbox, i_margin,
+                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &regionbbox, &bbox,
                                  VLC_CODEC_YUVA,
                                  YUVFromRGB,
                                  FillYUVAPicture,
                                  BlendYUVAPixel );
             else if( *p_chroma == VLC_CODEC_RGBA )
-                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &bbox, i_margin,
+                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &regionbbox, &bbox,
                                  VLC_CODEC_RGBA,
                                  RGBFromRGB,
                                  FillRGBAPicture,
                                  BlendRGBAPixel );
             else if( *p_chroma == VLC_CODEC_ARGB )
-                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &bbox, i_margin,
+                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &regionbbox, &bbox,
                                  VLC_CODEC_ARGB,
                                  RGBFromRGB,
                                  FillARGBPicture,



More information about the vlc-commits mailing list