[vlc-devel] [vlc-commits] text_renderer: freetype add support for ruby

Jean-Baptiste Kempf jb at videolan.org
Fri Feb 16 22:17:59 CET 2018


This (and the following commit) deserve a NEWS entry!

Also, gg!

On Fri, 16 Feb 2018, at 19:38, Francois Cartegnie wrote:
> vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Feb  
> 9 00:58:47 2018 +0100| [aa11155a67111520091f70a902b83436396158ee] | 
> committer: Francois Cartegnie
> 
> text_renderer: freetype add support for ruby
> 
> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=aa11155a67111520091f70a902b83436396158ee
> ---
> 
>  modules/text_renderer/freetype/freetype.c    |  91 +++++++++++-
>  modules/text_renderer/freetype/text_layout.c | 214 ++++++++++++++++++++++++++-
>  modules/text_renderer/freetype/text_layout.h |  19 ++-
>  3 files changed, 312 insertions(+), 12 deletions(-)
> 
> diff --git a/modules/text_renderer/freetype/freetype.c b/modules/
> text_renderer/freetype/freetype.c
> index 1802367349..bf76d49b0c 100644
> --- a/modules/text_renderer/freetype/freetype.c
> +++ b/modules/text_renderer/freetype/freetype.c
> @@ -841,6 +841,17 @@ static void RenderCharAXYZ( filter_t *p_filter,
>              break;
>          }
>  
> +        if(ch->p_ruby && ch->p_ruby->p_laid)
> +        {
> +            RenderCharAXYZ( p_filter,
> +                            p_picture,
> +                            ch->p_ruby->p_laid,
> +                            i_offset_x, i_offset_y,
> +                            2,
> +                            ExtractComponents,
> +                            BlendPixel );
> +        }
> +
>          /* Don't render if invisible or not wanted */
>          if( i_a == STYLE_ALPHA_TRANSPARENT ||
>             (g == 0 && 0 == (ch->p_style->i_style_flags & STYLE_SHADOW) ) ||
> @@ -1001,6 +1012,27 @@ static void FillDefaultStyles( filter_t *p_filter )
>      text_style_Merge( p_sys->p_default_style, p_sys->p_forced_style, true );
>  }
>  
> +static void FreeRubyBlockArray( ruby_block_t **pp_array, size_t 
> i_array )
> +{
> +    ruby_block_t *p_lyt = NULL;
> +    for( size_t i = 0; i< i_array; i++ )
> +    {
> +        if( p_lyt != pp_array[i] )
> +        {
> +            p_lyt = pp_array[i];
> +            if( p_lyt )
> +            {
> +                free( p_lyt->p_uchars );
> +                text_style_Delete( p_lyt->p_style );
> +                if( p_lyt->p_laid )
> +                    FreeLines( p_lyt->p_laid );
> +                free( p_lyt );
> +            }
> +        }
> +    }
> +    free( pp_array );
> +}
> +
>  static void FreeStylesArray( text_style_t **pp_styles, size_t 
> i_styles )
>  {
>      text_style_t *p_style = NULL;
> @@ -1016,7 +1048,8 @@ static void FreeStylesArray( text_style_t 
> **pp_styles, size_t i_styles )
>  }
>  
>  static size_t AddTextAndStyles( filter_sys_t *p_sys,
> -                                const char *psz_text, const 
> text_style_t *p_style,
> +                                const char *psz_text, const char 
> *psz_rt,
> +                                const text_style_t *p_style,
>                                  layout_text_block_t *p_text_block )
>  {
>      /* Convert chars to unicode */
> @@ -1046,6 +1079,15 @@ static size_t AddTextAndStyles( filter_sys_t 
> *p_sys,
>          return 0;
>      p_text_block->pp_styles = p_realloc;
>  
> +    /* Same for ruby text */
> +    if( SIZE_MAX / sizeof(text_segment_ruby_t *) < p_text_block-
> >i_count + i_newchars )
> +        return 0;
> +    i_realloc = (p_text_block->i_count + i_newchars) * 
> sizeof(text_segment_ruby_t *);
> +    p_realloc = realloc( p_text_block->pp_ruby, i_realloc );
> +    if ( unlikely(!p_realloc) )
> +        return 0;
> +    p_text_block->pp_ruby = p_realloc;
> +
>      /* Copy data */
>      memcpy( &p_text_block->p_uchars[p_text_block->i_count], p_ucs4, 
> i_newchars * 4 );
>      free( p_ucs4 );
> @@ -1065,6 +1107,33 @@ static size_t AddTextAndStyles( filter_sys_t 
> *p_sys,
>      for ( size_t i = 0; i < i_newchars; ++i )
>          p_text_block->pp_styles[p_text_block->i_count + i] = p_mgstyle;
>  
> +    ruby_block_t *p_rubyblock = NULL;
> +    if( psz_rt )
> +    {
> +        p_ucs4 = ToCharset( FREETYPE_TO_UCS, psz_rt, &i_bytes );
> +        if( !p_ucs4 )
> +            return 0;
> +        p_rubyblock = malloc(sizeof(ruby_block_t));
> +        if( p_rubyblock )
> +        {
> +            p_rubyblock->p_style = text_style_Duplicate( p_mgstyle );
> +            if( !p_rubyblock->p_style )
> +            {
> +                free( p_ucs4 );
> +                free( p_rubyblock );
> +                return 0;
> +            }
> +            p_rubyblock->p_style->i_font_size *= 0.4;
> +            p_rubyblock->p_style->f_font_relsize *= 0.4;
> +            p_rubyblock->p_uchars = p_ucs4;
> +            p_rubyblock->i_count = i_bytes / 4;
> +            p_rubyblock->p_laid = NULL;
> +        }
> +        else free( p_ucs4 );
> +    }
> +    for ( size_t i = 0; i < i_newchars; ++i )
> +        p_text_block->pp_ruby[p_text_block->i_count + i] = p_rubyblock;
> +
>      /* now safe to update total nb */
>      p_text_block->i_count += i_newchars;
>  
> @@ -1081,8 +1150,22 @@ static size_t SegmentsToTextAndStyles( filter_t 
> *p_filter, const text_segment_t
>          if( !s->psz_text || !s->psz_text[0] )
>              continue;
>  
> -        i_nb_char += AddTextAndStyles( p_filter->p_sys, s->psz_text,
> -                                       s->style, p_text_block );
> +        if( s->p_ruby )
> +        {
> +            for( const text_segment_ruby_t *p_ruby = s->p_ruby;
> +                                            p_ruby; p_ruby = p_ruby-
> >p_next )
> +            {
> +                i_nb_char += AddTextAndStyles( p_filter->p_sys,
> +                                               p_ruby->psz_base, 
> p_ruby->psz_rt,
> +                                               s->style, 
> p_text_block );
> +            }
> +        }
> +        else
> +        {
> +            i_nb_char += AddTextAndStyles( p_filter->p_sys,
> +                                           s->psz_text, NULL,
> +                                           s->style, p_text_block );
> +        }
>      }
>  
>      return i_nb_char;
> @@ -1283,6 +1366,8 @@ static int Render( filter_t *p_filter, 
> subpicture_region_t *p_region_out,
>  
>      free( text_block.p_uchars );
>      FreeStylesArray( text_block.pp_styles, text_block.i_count );
> +    if( text_block.pp_ruby )
> +        FreeRubyBlockArray( text_block.pp_ruby, text_block.i_count );
>      free( text_block.pi_k_durations );
>  
>      return rv;
> diff --git a/modules/text_renderer/freetype/text_layout.c b/modules/
> text_renderer/freetype/text_layout.c
> index ad998b2089..106d6f1ba1 100644
> --- a/modules/text_renderer/freetype/text_layout.c
> +++ b/modules/text_renderer/freetype/text_layout.c
> @@ -137,6 +137,7 @@ typedef struct paragraph_t
>      uni_char_t          *p_code_points;    /**< Unicode code points */
>      int                 *pi_glyph_indices; /**< Glyph index values 
> within the run's font face */
>      text_style_t       **pp_styles;
> +    ruby_block_t      **pp_ruby;
>      FT_Face             *pp_faces;         /**< Used to determine run 
> boundaries when performing font fallback */
>      int                 *pi_run_ids;       /**< The run to which each 
> glyph belongs */
>      glyph_bitmaps_t     *p_glyph_bitmaps;
> @@ -171,6 +172,9 @@ static void FreeLine( line_desc_t *p_line )
>              FT_Done_Glyph( (FT_Glyph)ch->p_shadow );
>      }
>  
> +//    if( p_line->p_ruby )
> +//        FreeLine( p_line->p_ruby );
> +
>      free( p_line->p_character );
>      free( p_line );
>  }
> @@ -210,6 +214,67 @@ line_desc_t *NewLine( int i_count )
>      return p_line;
>  }
>  
> +static void ShiftGlyph( FT_BitmapGlyph g, int x, int y )
> +{
> +    if( g )
> +    {
> +        g->left += x;
> +        g->top += y;
> +    }
> +}
> +
> +static void ShiftChar( line_character_t *c, int x, int y )
> +{
> +    ShiftGlyph( c->p_glyph, x, y );
> +    ShiftGlyph( c->p_shadow, x, y );
> +    ShiftGlyph( c->p_outline, x, y );
> +    c->bbox.yMin += y;
> +    c->bbox.yMax += y;
> +    c->bbox.xMin += x;
> +    c->bbox.xMax += x;
> +}
> +
> +static void ShiftLine( line_desc_t *p_line, int x, int y )
> +{
> +    for( int i=0; i<p_line->i_character_count; i++ )
> +        ShiftChar( &p_line->p_character[i], x, y );
> +    p_line->i_base_line += y;
> +    p_line->bbox.yMin += y;
> +    p_line->bbox.yMax += y;
> +    p_line->bbox.xMin += x;
> +    p_line->bbox.xMax += x;
> +}
> +
> +static void MoveLineTo( line_desc_t *p_line, int x, int y )
> +{
> +    ShiftLine( p_line, x - p_line->bbox.xMin,
> +                       y - p_line->bbox.yMax );
> +}
> +
> +static void IndentCharsFrom( line_desc_t *p_line, int i_start, int 
> i_count, int w, int h )
> +{
> +    for( int i=0; i<i_count; i++ )
> +    {
> +        line_character_t *p_ch = &p_line->p_character[i_start + i];
> +        ShiftChar( p_ch, w, h );
> +        BBoxEnlarge( &p_line->bbox, &p_ch->bbox );
> +    }
> +}
> +
> +static int RubyBaseAdvance( const line_desc_t *p_line, int i_start, int 
> *pi_count )
> +{
> +    int i_total = 0;
> +    *pi_count = 0;
> +    for( int i = i_start; i < p_line->i_character_count; i++ )
> +    {
> +        if( p_line->p_character[i].p_ruby != p_line-
> >p_character[i_start].p_ruby )
> +            break;
> +        (*pi_count)++;
> +        i_total += (p_line->p_character[i].bbox.xMax - p_line-
> >p_character[i].bbox.xMin);
> +    }
> +    return i_total;
> +}
> +
>  static void FixGlyph( FT_Glyph glyph, FT_BBox *p_bbox,
>                        FT_Pos i_x_advance, FT_Pos i_y_advance,
>                        const FT_Vector *p_pen )
> @@ -233,6 +298,7 @@ static paragraph_t *NewParagraph( filter_t 
> *p_filter,
>                                    int i_size,
>                                    const uni_char_t *p_code_points,
>                                    text_style_t **pp_styles,
> +                                  ruby_block_t **pp_ruby,
>                                    uint32_t *pi_k_dates,
>                                    int i_runs_size )
>  {
> @@ -255,6 +321,8 @@ static paragraph_t *NewParagraph( filter_t 
> *p_filter,
>              calloc( i_size, sizeof( *p_paragraph->p_glyph_bitmaps ) );
>      p_paragraph->pi_karaoke_bar =
>              calloc( i_size, sizeof( *p_paragraph->pi_karaoke_bar ) );
> +    if( pp_ruby )
> +        p_paragraph->pp_ruby = calloc( i_size, sizeof( *p_paragraph-
> >pp_ruby ) );
>  
>      p_paragraph->p_runs = calloc( i_runs_size, sizeof( run_desc_t ) );
>      p_paragraph->i_runs_size = i_runs_size;
> @@ -272,6 +340,9 @@ static paragraph_t *NewParagraph( filter_t *p_filter,
>      if( pp_styles )
>          memcpy( p_paragraph->pp_styles, pp_styles,
>                  i_size * sizeof( *pp_styles ) );
> +    if( p_paragraph->pp_ruby )
> +        memcpy( p_paragraph->pp_ruby, pp_ruby, i_size * sizeof( *pp_ruby ) );
> +
>      if( pi_k_dates )
>      {
>          int64_t i_elapsed  = var_GetInteger( p_filter, "spu-elapsed" ) / 1000;
> @@ -315,6 +386,7 @@ error:
>      if( p_paragraph->p_code_points ) free( p_paragraph->p_code_points );
>      if( p_paragraph->pi_glyph_indices ) free( p_paragraph->pi_glyph_indices );
>      if( p_paragraph->pp_styles ) free( p_paragraph->pp_styles );
> +    if( p_paragraph->pp_ruby ) free( p_paragraph->pp_ruby );
>      if( p_paragraph->pp_faces ) free( p_paragraph->pp_faces );
>      if( p_paragraph->pi_run_ids ) free( p_paragraph->pi_run_ids );
>      if( p_paragraph->p_glyph_bitmaps ) free( p_paragraph->p_glyph_bitmaps );
> @@ -341,6 +413,7 @@ static void FreeParagraph( paragraph_t *p_paragraph )
>      free( p_paragraph->pi_karaoke_bar );
>      free( p_paragraph->pi_run_ids );
>      free( p_paragraph->pp_faces );
> +    free( p_paragraph->pp_ruby );
>      free( p_paragraph->pp_styles );
>      free( p_paragraph->p_code_points );
>  
> @@ -732,13 +805,20 @@ static int ShapeParagraphHarfBuzz( filter_t *p_filter,
>          i_total_glyphs += p_run->i_glyph_count;
>      }
>  
> -    p_new_paragraph = NewParagraph( p_filter, i_total_glyphs, 0, 0, 0,
> +    p_new_paragraph = NewParagraph( p_filter, i_total_glyphs,
> +                                    NULL, NULL, NULL, NULL,
>                                      p_paragraph->i_runs_size );
>      if( !p_new_paragraph )
>      {
>          i_ret = VLC_ENOMEM;
>          goto error;
>      }
> +    if( p_paragraph->pp_ruby )
> +    {
> +        p_new_paragraph->pp_ruby = calloc(p_new_paragraph->i_size,
> +                                          sizeof(ruby_block_t *));
> +    }
> +
>      p_new_paragraph->paragraph_type = p_paragraph->paragraph_type;
>  
>      int i_index = 0;
> @@ -772,6 +852,9 @@ static int ShapeParagraphHarfBuzz( filter_t 
> *p_filter,
>                  p_paragraph->p_levels[ i_source_index ];
>              p_new_paragraph->pp_styles[ i_index ] =
>                  p_paragraph->pp_styles[ i_source_index ];
> +            if( p_new_paragraph->pp_ruby )
> +                p_new_paragraph->pp_ruby[ i_index ] =
> +                    p_paragraph->pp_ruby[ i_source_index ];
>              p_new_paragraph->pi_karaoke_bar[ i_index ] =
>                  p_paragraph->pi_karaoke_bar[ i_source_index ];
>              p_new_paragraph->p_glyph_bitmaps[ i_index ].i_x_offset =
> @@ -1056,7 +1139,8 @@ static int LoadGlyphs( filter_t *p_filter, 
> paragraph_t *p_paragraph,
>  static int LayoutLine( filter_t *p_filter,
>                         paragraph_t *p_paragraph,
>                         int i_first_char, int i_last_char,
> -                       line_desc_t **pp_line, bool b_grid )
> +                       bool b_grid,
> +                       line_desc_t **pp_line )
>  {
>      if( p_paragraph->i_size <= 0 || p_paragraph->i_runs_count <= 0
>       || i_first_char < 0 || i_last_char < 0
> @@ -1111,6 +1195,9 @@ static int LayoutLine( filter_t *p_filter,
>          line_character_t *p_ch = &p_line->p_character[p_line-
> >i_character_count];
>          p_ch->p_style = p_paragraph->pp_styles[ i_paragraph_index ];
>  
> +        if( p_paragraph->pp_ruby )
> +            p_ch->p_ruby = p_paragraph->pp_ruby[ i ];
> +
>          glyph_bitmaps_t *p_bitmaps =
>                  p_paragraph->p_glyph_bitmaps + i_paragraph_index;
>  
> @@ -1273,6 +1360,44 @@ static int LayoutLine( filter_t *p_filter,
>          p_line->i_character_count++;
>      }
>  
> +    /* Second pass for ruby layout */
> +    if( p_paragraph->pp_ruby )
> +    {
> +        const int i_ruby_baseline = p_line->bbox.yMax;
> +        const ruby_block_t *p_prevruby = NULL;
> +        for( int i = 0; i < p_line->i_character_count; ++i )
> +        {
> +            line_character_t *p_ch = &p_line->p_character[i];
> +            if( p_ch->p_ruby == p_prevruby || !p_ch->p_glyph )
> +                continue;
> +            p_prevruby = p_ch->p_ruby;
> +            if( !p_ch->p_ruby )
> +                continue;
> +            line_desc_t *p_rubyline = p_ch->p_ruby->p_laid;
> +            if( !p_rubyline )
> +                continue;
> +
> +            int i_rubyadvance = (p_rubyline->bbox.xMax - p_rubyline-
> >bbox.xMin);
> +            int i_rubyheight = (p_rubyline->bbox.yMax - p_rubyline-
> >bbox.yMin);
> +            MoveLineTo( p_rubyline, p_ch->bbox.xMin, i_ruby_baseline + 
> i_rubyheight );
> +            BBoxEnlarge( &p_line->bbox, &p_rubyline->bbox );
> +
> +            int i_count;
> +            int i_baseadvance = RubyBaseAdvance( p_line, i, &i_count );
> +            if( i_baseadvance < i_rubyadvance )
> +            {
> +                IndentCharsFrom( p_line, i, i_count, (i_rubyadvance - 
> i_baseadvance) / 2, 0 );
> +                IndentCharsFrom( p_line, i + i_count, p_line-
> >i_character_count - (i + i_count),
> +                                 (i_rubyadvance - i_baseadvance + 1), 
> 0 );
> +            }
> +            else if( i_baseadvance > i_rubyadvance + 1 )
> +            {
> +                ShiftLine( p_rubyline, (i_baseadvance - 
> i_rubyadvance) / 2, 0 );
> +                BBoxEnlarge( &p_line->bbox, &p_rubyline->bbox ); /* 
> shouldn't be needed */
> +            }
> +        }
> +    }
> +
>      p_line->i_width = __MAX( 0, p_line->bbox.xMax - p_line-
> >bbox.xMin );
>  
>      if( b_grid )
> @@ -1316,7 +1441,8 @@ static inline bool IsWhitespaceAt( paragraph_t 
> *p_paragraph, size_t i )
>  
>  static int LayoutParagraph( filter_t *p_filter, paragraph_t 
> *p_paragraph,
>                              unsigned i_max_width, unsigned 
> i_max_advance_x,
> -                            line_desc_t **pp_lines, bool b_grid, bool 
> b_balance )
> +                            bool b_grid, bool b_balance,
> +                            line_desc_t **pp_lines )
>  {
>      if( p_paragraph->i_size <= 0 || p_paragraph->i_runs_count <= 0 )
>      {
> @@ -1376,12 +1502,27 @@ static int LayoutParagraph( filter_t *p_filter, 
> paragraph_t *p_paragraph,
>          {
>              if( i_line_start < i )
>                  if( LayoutLine( p_filter, p_paragraph,
> -                                i_line_start, i - 1, pp_line, 
> b_grid ) )
> +                                i_line_start, i - 1, b_grid, 
> pp_line ) )
>                      goto error;
>  
>              break;
>          }
>  
> +        if( p_paragraph->pp_ruby &&
> +            p_paragraph->pp_ruby[i] &&
> +            p_paragraph->pp_ruby[i]->p_laid )
> +        {
> +            /* Just forward as non breakable */
> +            const ruby_block_t *p_rubyseq = p_paragraph->pp_ruby[i];
> +            int i_advance = 0;
> +            int i_advanceruby = p_rubyseq->p_laid->i_width;
> +            while( i < p_paragraph->i_size && p_rubyseq == p_paragraph-
> >pp_ruby[i] )
> +                i_advance += p_paragraph->p_glyph_bitmaps[ i+
> + ].i_x_advance;
> +            /* Just forward as non breakable */
> +            i_width += (i_advance < i_advanceruby) ? i_advanceruby : 
> i_advance;
> +            continue;
> +        }
> +
>          if( IsWhitespaceAt( p_paragraph, i ) )
>          {
>              if( i_line_start == i )
> @@ -1431,7 +1572,7 @@ static int LayoutParagraph( filter_t *p_filter, 
> paragraph_t *p_paragraph,
>                  i_newline_start = i; /* we break line on last char */
>  
>              if( LayoutLine( p_filter, p_paragraph, i_line_start,
> -                            i_newline_start - 1, pp_line, b_grid ) )
> +                            i_newline_start - 1, b_grid, pp_line ) )
>                  goto error;
>  
>              /* Handle early end of renderable content;
> @@ -1480,6 +1621,7 @@ static paragraph_t * BuildParagraph( filter_t *p_filter,
>                                       int i_size,
>                                       const uni_char_t *p_uchars,
>                                       text_style_t **pp_styles,
> +                                     ruby_block_t **pp_ruby,
>                                       uint32_t *pi_k_dates,
>                                       int i_runs_size,
>                                       unsigned *pi_max_advance_x )
> @@ -1487,6 +1629,7 @@ static paragraph_t * BuildParagraph( filter_t *p_filter,
>      paragraph_t *p_paragraph = NewParagraph( p_filter, i_size,
>                                  p_uchars,
>                                  pp_styles,
> +                                pp_ruby,
>                                  pi_k_dates,
>                                  i_runs_size );
>      if( !p_paragraph )
> @@ -1520,6 +1663,7 @@ static paragraph_t * BuildParagraph( filter_t *p_filter,
>      if( LoadGlyphs( p_filter, p_paragraph, false, true, pi_max_advance_x ) )
>          goto error;
>  #endif
> +
>      return p_paragraph;
>  
>  error:
> @@ -1529,6 +1673,43 @@ error:
>      return NULL;
>  }
>  
> +static int LayoutRubyText( filter_t *p_filter,
> +                           const uni_char_t *p_uchars,
> +                           int i_uchars,
> +                           text_style_t *p_style,
> +                           line_desc_t **pp_line )
> +{
> +    unsigned int i_max_advance_x;
> +
> +    text_style_t **pp_styles = malloc(sizeof(*pp_styles) * i_uchars);
> +    for(int i=0;i<i_uchars;i++)
> +        pp_styles[i] = p_style;
> +
> +    paragraph_t *p_paragraph = BuildParagraph( p_filter, i_uchars,
> +                                               p_uchars, pp_styles,
> +                                               NULL, NULL, 1,
> +                                               &i_max_advance_x );
> +    if( !p_paragraph )
> +    {
> +        free( pp_styles );
> +        return VLC_EGENERIC;
> +    }
> +
> +    if( LayoutLine( p_filter, p_paragraph,
> +                    0, i_uchars - 1,
> +                    false, pp_line ) )
> +    {
> +        free( pp_styles );
> +        FreeParagraph( p_paragraph );
> +        return VLC_EGENERIC;
> +    }
> +
> +    FreeParagraph( p_paragraph );
> +    free( pp_styles );
> +
> +    return VLC_SUCCESS;
> +}
> +
>  int LayoutTextBlock( filter_t *p_filter,
>                       const layout_text_block_t *p_textblock,
>                       line_desc_t **pp_lines, FT_BBox *p_bbox,
> @@ -1541,6 +1722,22 @@ int LayoutTextBlock( filter_t *p_filter,
>      unsigned i_max_advance_x = 0;
>      int i_max_face_height = 0;
>  
> +    /* Prepare ruby content */
> +    if( p_textblock->pp_ruby )
> +    {
> +        ruby_block_t *p_prev = NULL;
> +        for( size_t i=0; i<p_textblock->i_count; i++ )
> +        {
> +            if( p_textblock->pp_ruby[i] == p_prev )
> +                continue;
> +            p_prev = p_textblock->pp_ruby[i];
> +            if( p_prev )
> +                LayoutRubyText( p_filter, p_prev->p_uchars, p_prev-
> >i_count,
> +                                p_prev->p_style, &p_prev->p_laid );
> +        }
> +    }
> +    /* !Prepare ruby content */
> +
>      for( size_t i = 0; i <= p_textblock->i_count; ++i )
>      {
>          if( i == p_textblock->i_count || p_textblock->p_uchars[ i ] == 
> '\n' )
> @@ -1556,6 +1753,8 @@ int LayoutTextBlock( filter_t *p_filter,
>                                      i - i_paragraph_start,
>                                      &p_textblock-
> >p_uchars[i_paragraph_start],
>                                      &p_textblock-
> >pp_styles[i_paragraph_start],
> +                                    p_textblock->pp_ruby ?
> +                                    &p_textblock-
> >pp_ruby[i_paragraph_start] : NULL,
>                                      p_textblock->pi_k_durations ?
>                                      &p_textblock-
> >pi_k_durations[i_paragraph_start] : NULL,
>                                      20, &i_max_advance_x );
> @@ -1567,8 +1766,9 @@ int LayoutTextBlock( filter_t *p_filter,
>  
>              if( LayoutParagraph( p_filter, p_paragraph,
>                                   p_textblock->i_max_width,
> -                                 i_max_advance_x, pp_line,
> -                                 p_textblock->b_grid, p_textblock-
> >b_balanced ) )
> +                                 i_max_advance_x,
> +                                 p_textblock->b_grid, p_textblock-
> >b_balanced,
> +                                 pp_line ) )
>              {
>                  FreeParagraph( p_paragraph );
>                  if( p_first_line ) FreeLines( p_first_line );
> diff --git a/modules/text_renderer/freetype/text_layout.h b/modules/
> text_renderer/freetype/text_layout.h
> index ea0bca7558..bb31aac1b6 100644
> --- a/modules/text_renderer/freetype/text_layout.h
> +++ b/modules/text_renderer/freetype/text_layout.h
> @@ -33,6 +33,9 @@
>  
>  #include "freetype.h"
>  
> +typedef struct ruby_block_t ruby_block_t;
> +typedef struct line_desc_t line_desc_t;
> +
>  typedef struct
>  {
>      FT_BitmapGlyph p_glyph;
> @@ -40,16 +43,15 @@ typedef struct
>      FT_BitmapGlyph p_shadow;
>      FT_BBox        bbox;
>      const text_style_t *p_style;
> +    const ruby_block_t *p_ruby;
>      int            i_line_offset;       /* underline/strikethrough offset */
>      int            i_line_thickness;    /* underline/strikethrough thickness */
>      bool           b_in_karaoke;
>  } line_character_t;
>  
> -typedef struct line_desc_t line_desc_t;
>  struct line_desc_t
>  {
>      line_desc_t      *p_next;
> -
>      int              i_width;
>      int              i_height;
>      int              i_base_line;
> @@ -64,6 +66,18 @@ void FreeLines( line_desc_t *p_lines );
>  line_desc_t *NewLine( int i_count );
>  
>  /**
> + * \struct layout_ruby_t
> + * \brief LayoutText parameters
> + */
> +struct ruby_block_t
> +{
> +    uni_char_t *p_uchars;       /*!< array of size \p i_count character 
> codepoints */
> +    size_t i_count;             /*!< length of the array */
> +    text_style_t *p_style;      /*!< own style */
> +    line_desc_t *p_laid;
> +};
> +
> +/**
>   * \struct layout_text_block_t
>   * \brief LayoutText parameters
>   */
> @@ -71,6 +85,7 @@ typedef struct
>  {
>      uni_char_t *p_uchars;       /*!< array of size \p i_count character 
> codepoints */
>      text_style_t **pp_styles;   /*!< array of size \p i_count character 
> styles */
> +    ruby_block_t **pp_ruby;     /*!< array of size \p  */
>      uint32_t *pi_k_durations;   /*!< array of size \p i_count karaoke 
> timestamps */
>      size_t i_count;             /*!< length of the arrays */
>  
> 
> _______________________________________________
> vlc-commits mailing list
> vlc-commits at videolan.org
> https://mailman.videolan.org/listinfo/vlc-commits


-- 
Jean-Baptiste Kempf -  President
+33 672 704 734


More information about the vlc-devel mailing list