[vlc-commits] text_renderer: freetype: add support for regions larger than text

Francois Cartegnie git at videolan.org
Thu Nov 23 00:50:43 CET 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sun Nov 12 14:54:35 2017 +0100| [be9ea17a8cb29c23cbbf8bc3b3ab2f57ee5503ac] | committer: Francois Cartegnie

text_renderer: freetype: add support for regions larger than text

fixes sized regions positioning

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

 include/vlc_subpicture.h                  |   4 +-
 modules/codec/substext.h                  |  10 +++
 modules/text_renderer/freetype/freetype.c | 122 +++++++++++++++++++++++++-----
 3 files changed, 115 insertions(+), 21 deletions(-)

diff --git a/include/vlc_subpicture.h b/include/vlc_subpicture.h
index cb368c3a61..b9de52c049 100644
--- a/include/vlc_subpicture.h
+++ b/include/vlc_subpicture.h
@@ -70,8 +70,8 @@ struct subpicture_region_t
     bool            b_noregionbg;    /**< render background under text only */
     bool            b_gridmode;      /** if the decoder sends row/cols based output */
     bool            b_balanced_text; /** try to balance wrapped text lines */
-    int             i_max_width;     /** horizontal rendering/cropping limit */
-    int             i_max_height;    /** vertical rendering/cropping limit */
+    int             i_max_width;     /** horizontal rendering/cropping target/limit */
+    int             i_max_height;    /** vertical rendering/cropping target/limit */
 
     subpicture_region_t *p_next;                /**< next region in the list */
     subpicture_region_private_t *p_private;  /**< Private data for spu_t *only* */
diff --git a/modules/codec/substext.h b/modules/codec/substext.h
index f56eb25004..9db0cceaab 100644
--- a/modules/codec/substext.h
+++ b/modules/codec/substext.h
@@ -206,6 +206,16 @@ static void SubpictureTextUpdate(subpicture_t *subpic,
             else
                 r->i_y += p_updtregion->origin.y;
 
+            if( p_updtregion->flags & UPDT_REGION_EXTENT_X_IS_RATIO )
+                r->i_max_width += p_updtregion->extent.x * inner_w;
+            else
+                r->i_max_width += p_updtregion->extent.x;
+
+            if( p_updtregion->flags & UPDT_REGION_EXTENT_Y_IS_RATIO )
+                r->i_max_height += p_updtregion->extent.y * inner_h;
+            else
+                r->i_max_height += p_updtregion->extent.y;
+
         } else {
             /* FIXME it doesn't adapt on crop settings changes */
             r->i_x = p_updtregion->origin.x * fmt_dst->i_width  / p_updtregion->extent.x;
diff --git a/modules/text_renderer/freetype/freetype.c b/modules/text_renderer/freetype/freetype.c
index b8245e2d55..b7e4823e38 100644
--- a/modules/text_renderer/freetype/freetype.c
+++ b/modules/text_renderer/freetype/freetype.c
@@ -427,9 +427,11 @@ error:
  *****************************************************************************/
 static int RenderYUVP( filter_t *p_filter, subpicture_region_t *p_region,
                        line_desc_t *p_line,
-                       FT_BBox *p_regionbbox, FT_BBox *p_bbox )
+                       FT_BBox *p_regionbbox, FT_BBox *p_paddedbbox,
+                       FT_BBox *p_bbox )
 {
     VLC_UNUSED(p_filter);
+    VLC_UNUSED(p_paddedbbox);
     static const uint8_t pi_gamma[16] =
         {0x00, 0x52, 0x84, 0x96, 0xb8, 0xca, 0xdc, 0xee, 0xff,
           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
@@ -725,11 +727,14 @@ 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_regionbbox,
+                                     FT_BBox *p_paddedbbox,
                                      FT_BBox *p_textbbox,
                                      picture_t *p_picture,
                                      void (*ExtractComponents)( uint32_t, uint8_t *, uint8_t *, uint8_t * ),
                                      void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) )
 {
+    FT_BBox prevbox;
+
     for( const line_desc_t *p_line = p_line_head; p_line != NULL; p_line = p_line->p_next )
     {
         FT_Vector offset = GetAlignedOffset( p_line, p_textbbox, p_region->i_text_align );
@@ -743,6 +748,11 @@ static inline void RenderBackground( subpicture_region_t *p_region,
         if( p_line->i_first_visible_char_index < 0 )
             continue; /* only spaces */
 
+        /* add padding */
+        linebgbox.yMax += (p_paddedbbox->xMax - p_textbbox->xMax);
+        linebgbox.yMin -= (p_textbbox->xMin - p_paddedbbox->xMin);
+        linebgbox.xMin -= (p_textbbox->xMin - p_paddedbbox->xMin);
+        linebgbox.xMax += (p_paddedbbox->xMax - p_textbbox->xMax);
 
         /* Compute lower boundary for the background
            continue down to next line top */
@@ -758,7 +768,8 @@ static inline void RenderBackground( subpicture_region_t *p_region,
         if( i_char_index > 0 )
         {
             segmentbgbox.xMin = offset.x +
-                                p_line->p_character[p_line->i_first_visible_char_index].bbox.xMin;
+                                p_line->p_character[p_line->i_first_visible_char_index].bbox.xMin -
+                                /* padding offset */ (p_textbbox->xMin - p_paddedbbox->xMin);
         }
 
         while( i_char_index <= p_line->i_last_visible_char_index )
@@ -773,6 +784,8 @@ static inline void RenderBackground( subpicture_region_t *p_region,
 
             /* Find right boundary for bounding box for background */
             segmentbgbox.xMax = offset.x + p_line->p_character[i_seg_end].bbox.xMax;
+            if( i_seg_end == p_line->i_last_visible_char_index ) /* add padding on last */
+                segmentbgbox.xMax += (p_paddedbbox->xMax - p_textbbox->xMax);
 
             const line_character_t *p_char = &p_line->p_character[i_char_index];
             if( p_char->p_style->i_style_flags & STYLE_BACKGROUND )
@@ -818,6 +831,7 @@ static inline int RenderAXYZ( filter_t *p_filter,
                               subpicture_region_t *p_region,
                               line_desc_t *p_line_head,
                               FT_BBox *p_regionbbox,
+                              FT_BBox *p_paddedtextbbox,
                               FT_BBox *p_textbbox,
                               vlc_fourcc_t i_chroma,
                               void (*ExtractComponents)( uint32_t, uint8_t *, uint8_t *, uint8_t * ),
@@ -857,8 +871,9 @@ static inline int RenderAXYZ( filter_t *p_filter,
     }
 
     /* Render text's background (from decoder) if any */
-    RenderBackground(p_region, p_line_head, p_regionbbox, p_textbbox, p_picture,
-                     ExtractComponents, BlendPixel);
+    RenderBackground(p_region, p_line_head,
+                     p_regionbbox, p_paddedtextbbox, p_textbbox,
+                     p_picture, ExtractComponents, BlendPixel);
 
     /* Render shadow then outline and then normal glyphs */
     for( int g = 0; g < 3; g++ )
@@ -1136,14 +1151,18 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
     else if( p_region_in->i_y > 0 && (unsigned)p_region_in->i_y < i_max_height )
         i_max_height -= p_region_in->i_y;
 
+    uint8_t i_background_opacity = var_InheritInteger( p_filter, "freetype-background-opacity" );
+    i_background_opacity = VLC_CLIP( i_background_opacity, 0, 255 );
+    int i_margin = (i_background_opacity > 0 && !p_region_in->b_gridmode) ? i_max_face_height / 4 : 0;
+
+    if( (unsigned)i_margin * 2 >= i_max_width || (unsigned)i_margin * 2 >= i_max_height )
+        i_margin = 0;
+
     rv = LayoutText( p_filter,
                      psz_text, pp_styles, pi_k_durations, i_text_length,
                      p_region_in->b_gridmode, p_region_in->b_balanced_text,
                      i_max_width, i_max_height, &p_lines, &bbox, &i_max_face_height );
 
-    p_region_out->i_x = p_region_in->i_x;
-    p_region_out->i_y = p_region_in->i_y;
-
     /* Don't attempt to render text that couldn't be layed out
      * properly. */
     if( !rv && i_text_length > 0 && bbox.xMin < bbox.xMax && bbox.yMin < bbox.yMax )
@@ -1156,35 +1175,100 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
         else if( !p_chroma_list || *p_chroma_list == 0 )
             p_chroma_list = p_chroma_list_rgba;
 
-        uint8_t i_background_opacity = var_InheritInteger( p_filter, "freetype-background-opacity" );
-        i_background_opacity = VLC_CLIP( i_background_opacity, 0, 255 );
-        int i_margin = (i_background_opacity > 0 && !p_region_in->b_gridmode) ? i_max_face_height / 4 : 0;
+        FT_BBox paddedbbox = bbox;
+        paddedbbox.xMin -= i_margin;
+        paddedbbox.xMax += i_margin;
+        paddedbbox.yMin -= i_margin;
+        paddedbbox.yMax += i_margin;
+
+        FT_BBox regionbbox = paddedbbox;
+
+        /* _______regionbbox_______________
+         * |                               |
+         * |                               |
+         * |                               |
+         * |     _bbox(<paddedbbox)___     |
+         * |    |         rightaligned|    |
+         * |    |            textlines|    |
+         * |    |_____________________|    |
+         * |_______________________________|
+         *
+         * we need at least 3 bounding boxes.
+         * regionbbox containing the whole, including region background pixels
+         * paddedbox an enlarged text box when for drawing text background
+         * bbox the lines bounding box for all glyphs
+         * For simple unstyled subs, bbox == paddedbox == regionbbox
+         */
+
+        unsigned outertext_w = (regionbbox.xMax - regionbbox.xMin);
+        if( outertext_w < (unsigned) p_region_in->i_max_width )
+        {
+            if( p_region_in->i_text_align & SUBPICTURE_ALIGN_RIGHT )
+                regionbbox.xMin -= (p_region_in->i_max_width - outertext_w);
+            else if( p_region_in->i_text_align & SUBPICTURE_ALIGN_LEFT )
+                regionbbox.xMax += (p_region_in->i_max_width - outertext_w);
+            else
+            {
+                regionbbox.xMin -= (p_region_in->i_max_width - outertext_w) / 2;
+                regionbbox.xMax += (p_region_in->i_max_width - outertext_w + 1) / 2;
+            }
+        }
+
+        unsigned outertext_h = (regionbbox.yMax - regionbbox.yMin);
+        if( outertext_h < (unsigned) p_region_in->i_max_height )
+        {
+            if( p_region_in->i_text_align & SUBPICTURE_ALIGN_TOP )
+                regionbbox.yMin -= (p_region_in->i_max_height - outertext_h);
+            else if( p_region_in->i_text_align & SUBPICTURE_ALIGN_BOTTOM )
+                regionbbox.yMax += (p_region_in->i_max_height - outertext_h);
+            else
+            {
+                regionbbox.yMin -= (p_region_in->i_max_height - outertext_h + 1) / 2;
+                regionbbox.yMax += (p_region_in->i_max_height - outertext_h) / 2;
+            }
+        }
+
+//        unsigned bboxcolor = 0xFF000000;
+        /* TODO 4.0. No region self BG color for VLC 3.0 API*/
 
-        FT_BBox regionbbox = bbox;
-        regionbbox.xMin -= i_margin;
-        regionbbox.xMax += i_margin;
-        regionbbox.yMin -= i_margin;
-        regionbbox.yMax += i_margin;
+        /* Avoid useless pixels:
+         *        reshrink/trim Region Box to padded text one,
+         *        but update offsets to keep position and have same rendering */
+//        if( (bboxcolor & 0xFF) == 0 )
+        {
+            p_region_out->i_x = (paddedbbox.xMin - regionbbox.xMin) + p_region_in->i_x;
+            p_region_out->i_y = (regionbbox.yMax - paddedbbox.yMax) + p_region_in->i_y;
+            regionbbox = paddedbbox;
+        }
+//        else /* case where the bounding box is larger and visible */
+//        {
+//            p_region_out->i_x = p_region_in->i_x;
+//            p_region_out->i_y = p_region_in->i_y;
+//        }
 
         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, &regionbbox, &bbox );
+                rv = RenderYUVP( p_filter, p_region_out, p_lines,
+                                 &regionbbox, &paddedbbox, &bbox );
             else if( *p_chroma == VLC_CODEC_YUVA )
-                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &regionbbox, &bbox,
+                rv = RenderAXYZ( p_filter, p_region_out, p_lines,
+                                 &regionbbox, &paddedbbox, &bbox,
                                  VLC_CODEC_YUVA,
                                  YUVFromRGB,
                                  FillYUVAPicture,
                                  BlendYUVAPixel );
             else if( *p_chroma == VLC_CODEC_RGBA )
-                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &regionbbox, &bbox,
+                rv = RenderAXYZ( p_filter, p_region_out, p_lines,
+                                 &regionbbox, &paddedbbox, &bbox,
                                  VLC_CODEC_RGBA,
                                  RGBFromRGB,
                                  FillRGBAPicture,
                                  BlendRGBAPixel );
             else if( *p_chroma == VLC_CODEC_ARGB )
-                rv = RenderAXYZ( p_filter, p_region_out, p_lines, &regionbbox, &bbox,
+                rv = RenderAXYZ( p_filter, p_region_out, p_lines,
+                                 &regionbbox, &paddedbbox, &bbox,
                                  VLC_CODEC_ARGB,
                                  RGBFromRGB,
                                  FillARGBPicture,



More information about the vlc-commits mailing list