[vlc-devel] [PATCH 3/9] freetype: remove remaining layout code from freetype.c
Salah-Eddin Shaban
salshaaban at gmail.com
Sat Apr 18 19:56:15 CEST 2015
---
modules/text_renderer/freetype.c | 467 ---------------------------------------
1 file changed, 467 deletions(-)
diff --git a/modules/text_renderer/freetype.c b/modules/text_renderer/freetype.c
index a52b24c..4668f07 100644
--- a/modules/text_renderer/freetype.c
+++ b/modules/text_renderer/freetype.c
@@ -928,473 +928,6 @@ static FT_Face LoadFace( filter_t *p_filter,
return p_face;
}
-static int ProcessLines( filter_t *p_filter,
- line_desc_t **pp_lines,
- FT_BBox *p_bbox,
- int *pi_max_face_height,
-
- uni_char_t *psz_text,
- text_style_t **pp_styles,
- uint32_t *pi_k_dates,
- int i_len )
-{
- filter_sys_t *p_sys = p_filter->p_sys;
- uni_char_t *p_fribidi_string = NULL;
- text_style_t **pp_fribidi_styles = NULL;
- int *p_new_positions = NULL;
-
-#if defined(HAVE_FRIBIDI)
- {
- int *p_old_positions;
- int start_pos, pos = 0;
-
- pp_fribidi_styles = calloc( i_len, sizeof(*pp_fribidi_styles) );
-
- p_fribidi_string = malloc( (i_len + 1) * sizeof(*p_fribidi_string) );
- p_old_positions = malloc( (i_len + 1) * sizeof(*p_old_positions) );
- p_new_positions = malloc( (i_len + 1) * sizeof(*p_new_positions) );
-
- if( ! pp_fribidi_styles ||
- ! p_fribidi_string ||
- ! p_old_positions ||
- ! p_new_positions )
- {
- free( p_old_positions );
- free( p_new_positions );
- free( p_fribidi_string );
- free( pp_fribidi_styles );
- return VLC_ENOMEM;
- }
-
- /* Do bidi conversion line-by-line */
- while(pos < i_len)
- {
- while(pos < i_len) {
- if (psz_text[pos] != '\n')
- break;
- p_fribidi_string[pos] = psz_text[pos];
- pp_fribidi_styles[pos] = pp_styles[pos];
- p_new_positions[pos] = pos;
- ++pos;
- }
- start_pos = pos;
- while(pos < i_len) {
- if (psz_text[pos] == '\n')
- break;
- ++pos;
- }
- if (pos > start_pos)
- {
-#if (FRIBIDI_MINOR_VERSION < 19) && (FRIBIDI_MAJOR_VERSION == 0)
- FriBidiCharType base_dir = FRIBIDI_TYPE_LTR;
-#else
- FriBidiParType base_dir = FRIBIDI_PAR_LTR;
-#endif
- fribidi_log2vis((FriBidiChar*)psz_text + start_pos,
- pos - start_pos, &base_dir,
- (FriBidiChar*)p_fribidi_string + start_pos,
- p_new_positions + start_pos,
- p_old_positions,
- NULL );
- for( int j = start_pos; j < pos; j++ )
- {
- pp_fribidi_styles[ j ] = pp_styles[ start_pos + p_old_positions[j - start_pos] ];
- p_new_positions[ j ] += start_pos;
- }
- }
- }
- p_fribidi_string[ i_len ] = 0;
- free( p_old_positions );
-
- pp_styles = pp_fribidi_styles;
- psz_text = p_fribidi_string;
- }
-#endif
- /* Work out the karaoke */
- uint8_t *pi_karaoke_bar = NULL;
- if( pi_k_dates )
- {
- pi_karaoke_bar = malloc( i_len * sizeof(*pi_karaoke_bar));
- if( pi_karaoke_bar )
- {
- int64_t i_elapsed = var_GetTime( p_filter, "spu-elapsed" ) / 1000;
- for( int i = 0; i < i_len; i++ )
- {
- unsigned i_bar = p_new_positions ? p_new_positions[i] : i;
- pi_karaoke_bar[i_bar] = pi_k_dates[i] >= i_elapsed;
- }
- }
- }
- free( p_new_positions );
-
- *pi_max_face_height = 0;
- *pp_lines = NULL;
- line_desc_t **pp_line_next = pp_lines;
-
- FT_BBox bbox = {
- .xMin = INT_MAX,
- .yMin = INT_MAX,
- .xMax = INT_MIN,
- .yMax = INT_MIN,
- };
- int i_face_height_previous = 0;
- int i_base_line = 0;
- const text_style_t *p_previous_style = NULL;
- FT_Face p_face = NULL;
- for( int i_start = 0; i_start < i_len; )
- {
- /* Compute the length of the current text line */
- int i_length = 0;
- while( i_start + i_length < i_len && psz_text[i_start + i_length] != '\n' )
- i_length++;
-
- /* Render the text line (or the begining if too long) into 0 or 1 glyph line */
- line_desc_t *p_line = i_length > 0 ? NewLine( i_length ) : NULL;
- int i_index = i_start;
- FT_Vector pen = {
- .x = 0,
- .y = 0,
- };
- int i_face_height = 0;
- FT_BBox line_bbox = {
- .xMin = INT_MAX,
- .yMin = INT_MAX,
- .xMax = INT_MIN,
- .yMax = INT_MIN,
- };
- int i_ul_offset = 0;
- int i_ul_thickness = 0;
- typedef struct {
- int i_index;
- FT_Vector pen;
- FT_BBox line_bbox;
- int i_face_height;
- int i_ul_offset;
- int i_ul_thickness;
- } break_point_t;
- break_point_t break_point;
- break_point_t break_point_fallback;
-
-#define SAVE_BP(dst) do { \
- dst.i_index = i_index; \
- dst.pen = pen; \
- dst.line_bbox = line_bbox; \
- dst.i_face_height = i_face_height; \
- dst.i_ul_offset = i_ul_offset; \
- dst.i_ul_thickness = i_ul_thickness; \
- } while(0)
-
- SAVE_BP( break_point );
- SAVE_BP( break_point_fallback );
-
- while( i_index < i_start + i_length )
- {
- /* Split by common FT_Face + Size */
- const text_style_t *p_current_style = pp_styles[i_index];
- int i_part_length = 0;
- while( i_index + i_part_length < i_start + i_length )
- {
- const text_style_t *p_style = pp_styles[i_index + i_part_length];
- if( !FaceStyleEquals( p_style, p_current_style ) ||
- p_style->i_font_size != p_current_style->i_font_size )
- break;
- i_part_length++;
- }
-
- /* (Re)load/reconfigure the face if needed */
- if( !FaceStyleEquals( p_current_style, p_previous_style ) )
- {
- if( p_face )
- FT_Done_Face( p_face );
- p_previous_style = NULL;
-
- p_face = LoadFace( p_filter, p_current_style );
- }
- FT_Face p_current_face = p_face ? p_face : p_sys->p_face;
- if( !p_previous_style || p_previous_style->i_font_size != p_current_style->i_font_size ||
- ((p_previous_style->i_style_flags ^ p_current_style->i_style_flags) & STYLE_HALFWIDTH) )
-
- {
- int i_font_width = ( p_current_style->i_style_flags & STYLE_HALFWIDTH )
- ? p_current_style->i_font_size / 2
- : p_current_style->i_font_size;
- if( FT_Set_Pixel_Sizes( p_current_face,
- i_font_width,
- p_current_style->i_font_size ) )
- msg_Err( p_filter, "Failed to set font size to %d", p_current_style->i_font_size );
- if( p_sys->p_stroker )
- {
- double f_outline_thickness = var_InheritInteger( p_filter, "freetype-outline-thickness" ) / 100.0;
- f_outline_thickness = VLC_CLIP( f_outline_thickness, 0.0, 0.5 );
- int i_radius = (p_current_style->i_font_size << 6) * f_outline_thickness;
- FT_Stroker_Set( p_sys->p_stroker,
- i_radius,
- FT_STROKER_LINECAP_ROUND,
- FT_STROKER_LINEJOIN_ROUND, 0 );
- }
- }
- p_previous_style = p_current_style;
-
- i_face_height = __MAX(i_face_height, FT_CEIL(FT_MulFix(p_current_face->height,
- p_current_face->size->metrics.y_scale)));
-
- /* Render the part */
- bool b_break_line = false;
- int i_glyph_last = 0;
- FT_Vector advance = {
- .x = 0,
- .y = 0,
- };
- while( i_part_length > 0 )
- {
- const text_style_t *p_glyph_style = pp_styles[i_index];
- uni_char_t character = psz_text[i_index];
- int i_glyph_index = FT_Get_Char_Index( p_current_face, character );
-
- /* If the missing glyph is U+FEFF (ZERO WIDTH NO-BREAK SPACE) */
- /* we can safely ignore it. Otherwise extra squares show up */
- /* in Arabic text. */
- if( i_glyph_index == 0 && character == 0xFEFF )
- goto next;
-
-/* These are the most common Arabic diacritics */
-#define DIACRITIC( a ) ( a >= 0x064B && a <= 0x0653 )
-
- /* Diacritics should be rendered over the preceding base glyph */
- if( DIACRITIC( character ) )
- {
- pen.x -= advance.x;
- pen.y -= advance.y;
- }
-
- /* Get kerning vector */
- FT_Vector kerning = { .x = 0, .y = 0 };
- if( FT_HAS_KERNING( p_current_face ) && i_glyph_last != 0 && i_glyph_index != 0 )
- {
- FT_Get_Kerning( p_current_face, i_glyph_last, i_glyph_index, ft_kerning_default, &kerning );
- }
- if( p_glyph_style->i_spacing > 0 && i_glyph_last != 0 && i_glyph_index != 0 )
- {
- kerning.x = (p_glyph_style->i_spacing) << 6;
- }
-
- /* Get the glyph bitmap and its bounding box and all the associated properties */
- FT_Vector pen_new = {
- .x = pen.x + kerning.x,
- .y = pen.y + kerning.y,
- };
-
- int i_font_width = ( p_current_style->i_style_flags & STYLE_HALFWIDTH )
- ? p_current_style->i_font_size / 2
- : p_current_style->i_font_size;
- FT_Vector pen_shadow_new = {
- .x = pen_new.x + p_sys->f_shadow_vector_x * (i_font_width << 6),
- .y = pen_new.y + p_sys->f_shadow_vector_y * (p_current_style->i_font_size << 6),
- };
-
- FT_Glyph glyph;
- FT_BBox glyph_bbox;
- FT_Glyph outline;
- FT_BBox outline_bbox;
- FT_Glyph shadow;
- FT_BBox shadow_bbox;
-
- if( GetGlyph( p_filter,
- &glyph, &glyph_bbox,
- &outline, &outline_bbox,
- &shadow, &shadow_bbox,
- p_current_face, i_glyph_index, p_glyph_style->i_style_flags,
- &pen_new, &pen_shadow_new ) )
- goto next;
-
- FixGlyph( glyph, &glyph_bbox, p_current_face, &pen_new );
- if( outline )
- FixGlyph( outline, &outline_bbox, p_current_face, &pen_new );
- if( shadow )
- FixGlyph( shadow, &shadow_bbox, p_current_face, &pen_shadow_new );
-
- /* FIXME and what about outline */
-
- bool b_karaoke = pi_karaoke_bar && pi_karaoke_bar[i_index] != 0;
- uint32_t i_color = b_karaoke ? (p_glyph_style->i_karaoke_background_color |
- (p_glyph_style->i_karaoke_background_alpha << 24))
- : (p_glyph_style->i_font_color |
- (p_glyph_style->i_font_alpha << 24));
- int i_line_offset = 0;
- int i_line_thickness = 0;
- if( p_glyph_style->i_style_flags & (STYLE_UNDERLINE | STYLE_STRIKEOUT) )
- {
- i_line_offset = abs( FT_FLOOR(FT_MulFix(p_current_face->underline_position,
- p_current_face->size->metrics.y_scale)) );
-
- i_line_thickness = abs( FT_CEIL(FT_MulFix(p_current_face->underline_thickness,
- p_current_face->size->metrics.y_scale)) );
-
- if( p_glyph_style->i_style_flags & STYLE_STRIKEOUT )
- {
- /* Move the baseline to make it strikethrough instead of
- * underline. That means that strikethrough takes precedence
- */
- i_line_offset -= abs( FT_FLOOR(FT_MulFix(p_current_face->descender*2,
- p_current_face->size->metrics.y_scale)) );
- }
- else if( i_line_thickness > 0 )
- {
- glyph_bbox.yMin = __MIN( glyph_bbox.yMin, - i_line_offset - i_line_thickness );
-
- /* The real underline thickness and position are
- * updated once the whole line has been parsed */
- i_ul_offset = __MAX( i_ul_offset, i_line_offset );
- i_ul_thickness = __MAX( i_ul_thickness, i_line_thickness );
- i_line_thickness = -1;
- }
- }
- FT_BBox line_bbox_new = line_bbox;
- BBoxEnlarge( &line_bbox_new, &glyph_bbox );
- if( outline )
- BBoxEnlarge( &line_bbox_new, &outline_bbox );
- if( shadow )
- BBoxEnlarge( &line_bbox_new, &shadow_bbox );
-
- b_break_line = i_index > i_start &&
- line_bbox_new.xMax - line_bbox_new.xMin >= (int)p_filter->fmt_out.video.i_visible_width;
- if( b_break_line )
- {
- FT_Done_Glyph( glyph );
- if( outline )
- FT_Done_Glyph( outline );
- if( shadow )
- FT_Done_Glyph( shadow );
-
- break_point_t *p_bp = NULL;
- if( break_point.i_index > i_start )
- p_bp = &break_point;
- else if( break_point_fallback.i_index > i_start )
- p_bp = &break_point_fallback;
-
- if( p_bp )
- {
- msg_Dbg( p_filter, "Breaking line");
- for( int i = p_bp->i_index; i < i_index; i++ )
- {
- line_character_t *ch = &p_line->p_character[i - i_start];
- FT_Done_Glyph( (FT_Glyph)ch->p_glyph );
- if( ch->p_outline )
- FT_Done_Glyph( (FT_Glyph)ch->p_outline );
- if( ch->p_shadow )
- FT_Done_Glyph( (FT_Glyph)ch->p_shadow );
- }
- p_line->i_character_count = p_bp->i_index - i_start;
-
- i_index = p_bp->i_index;
- pen = p_bp->pen;
- line_bbox = p_bp->line_bbox;
- i_face_height = p_bp->i_face_height;
- i_ul_offset = p_bp->i_ul_offset;
- i_ul_thickness = p_bp->i_ul_thickness;
- }
- else
- {
- msg_Err( p_filter, "Breaking unbreakable line");
- }
- break;
- }
-
- p_line->p_character[p_line->i_character_count++] = (line_character_t){
- .p_glyph = (FT_BitmapGlyph)glyph,
- .p_outline = (FT_BitmapGlyph)outline,
- .p_shadow = (FT_BitmapGlyph)shadow,
- .i_color = i_color,
- .i_line_offset = i_line_offset,
- .i_line_thickness = i_line_thickness,
- };
-
- /* Diacritics do not determine advance values. We use */
- /* the advance values from the last encountered base glyph, */
- /* since multiple diacritics may follow a single base glyph. */
- if( !DIACRITIC( character ) )
- {
- advance.x = p_current_face->glyph->advance.x;
- advance.y = p_current_face->glyph->advance.y;
- }
-
- pen.x = pen_new.x + advance.x;
- pen.y = pen_new.y + advance.y;
- line_bbox = line_bbox_new;
- next:
- i_glyph_last = i_glyph_index;
- i_part_length--;
- i_index++;
-
- if( character == ' ' || character == '\t' )
- SAVE_BP( break_point );
- else if( character == 160 )
- SAVE_BP( break_point_fallback );
- }
- if( b_break_line )
- break;
- }
-#undef SAVE_BP
- /* Update our baseline */
- if( i_face_height_previous > 0 )
- i_base_line += __MAX(i_face_height, i_face_height_previous);
- if( i_face_height > 0 )
- i_face_height_previous = i_face_height;
-
- /* Update the line bbox with the actual base line */
- if (line_bbox.yMax > line_bbox.yMin) {
- line_bbox.yMin -= i_base_line;
- line_bbox.yMax -= i_base_line;
- }
- BBoxEnlarge( &bbox, &line_bbox );
-
- /* Terminate and append the line */
- if( p_line )
- {
- p_line->i_width = __MAX(line_bbox.xMax - line_bbox.xMin, 0);
- p_line->i_base_line = i_base_line;
- p_line->i_height = __MAX(i_face_height, i_face_height_previous);
- if( i_ul_thickness > 0 )
- {
- for( int i = 0; i < p_line->i_character_count; i++ )
- {
- line_character_t *ch = &p_line->p_character[i];
- if( ch->i_line_thickness < 0 )
- {
- ch->i_line_offset = i_ul_offset;
- ch->i_line_thickness = i_ul_thickness;
- }
- }
- }
-
- *pp_line_next = p_line;
- pp_line_next = &p_line->p_next;
- }
-
- *pi_max_face_height = __MAX( *pi_max_face_height, i_face_height );
-
- /* Skip what we have rendered and the line delimitor if present */
- i_start = i_index;
- if( i_start < i_len && psz_text[i_start] == '\n' )
- i_start++;
-
- if( bbox.yMax - bbox.yMin >= (int)p_filter->fmt_out.video.i_visible_height )
- {
- msg_Err( p_filter, "Truncated too high subtitle" );
- break;
- }
- }
- if( p_face )
- FT_Done_Face( p_face );
-
- free( pp_fribidi_styles );
- free( p_fribidi_string );
- free( pi_karaoke_bar );
-
- *p_bbox = bbox;
- return VLC_SUCCESS;
-}
-
static xml_reader_t *GetXMLReader( filter_t *p_filter, stream_t *p_sub )
{
xml_reader_t *p_xml_reader = p_filter->p_sys->p_xml;
--
1.9.1
More information about the vlc-devel
mailing list