[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, ®ionbbox, &bbox );
+ rv = RenderYUVP( p_filter, p_region_out, p_lines,
+ ®ionbbox, &paddedbbox, &bbox );
else if( *p_chroma == VLC_CODEC_YUVA )
- rv = RenderAXYZ( p_filter, p_region_out, p_lines, ®ionbbox, &bbox,
+ rv = RenderAXYZ( p_filter, p_region_out, p_lines,
+ ®ionbbox, &paddedbbox, &bbox,
VLC_CODEC_YUVA,
YUVFromRGB,
FillYUVAPicture,
BlendYUVAPixel );
else if( *p_chroma == VLC_CODEC_RGBA )
- rv = RenderAXYZ( p_filter, p_region_out, p_lines, ®ionbbox, &bbox,
+ rv = RenderAXYZ( p_filter, p_region_out, p_lines,
+ ®ionbbox, &paddedbbox, &bbox,
VLC_CODEC_RGBA,
RGBFromRGB,
FillRGBAPicture,
BlendRGBAPixel );
else if( *p_chroma == VLC_CODEC_ARGB )
- rv = RenderAXYZ( p_filter, p_region_out, p_lines, ®ionbbox, &bbox,
+ rv = RenderAXYZ( p_filter, p_region_out, p_lines,
+ ®ionbbox, &paddedbbox, &bbox,
VLC_CODEC_ARGB,
RGBFromRGB,
FillARGBPicture,
More information about the vlc-commits
mailing list