[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, ®ionbbox, &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, ®ionbbox, &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, ®ionbbox, &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, ®ionbbox, &bbox,
VLC_CODEC_ARGB,
RGBFromRGB,
FillARGBPicture,
More information about the vlc-commits
mailing list