Changeset 2293854f363396b56fc15db8d903e26e1b631383
- Timestamp:
- 10/07/07 22:15:14 (1 year ago)
- git-parent:
- Files:
-
- modules/misc/freetype.c (modified) (46 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
modules/misc/freetype.c
r4d4eb33 r2293854 97 97 98 98 static int SetFontSize( filter_t *, int ); 99 static void YUVFromRGB( uint32_t i_argb, 100 uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v ); 99 101 100 102 /***************************************************************************** … … 194 196 * b_new_color_mode is set, then it becomes possible to 195 197 * have multicoloured text within the subtitles. */ 196 uint32_t *p_rgb; 198 uint32_t *p_fg_rgb; 199 uint32_t *p_bg_rgb; 200 uint8_t *p_fg_bg_ratio; /* 0x00=100% FG --> 0x7F=100% BG */ 197 201 vlc_bool_t b_new_color_mode; 198 202 /** underline information -- only supplied if text should be underlined */ … … 213 217 char *psz_name; 214 218 int i_size; 215 int i_color;216 int i_alpha;219 uint32_t i_color; /* ARGB */ 220 uint32_t i_karaoke_bg_color; /* ARGB */ 217 221 218 222 font_stack_t *p_next; … … 222 226 { 223 227 int i_font_size; 224 uint32_t i_font_color; /* ARGB */ 228 uint32_t i_font_color; /* ARGB */ 229 uint32_t i_karaoke_bg_color; /* ARGB */ 225 230 vlc_bool_t b_italic; 226 231 vlc_bool_t b_bold; … … 712 717 713 718 /* Calculate text color components */ 714 i_y = (uint8_t)__MIN(abs( 2104 * p_line->i_red + 4130 * p_line->i_green + 715 802 * p_line->i_blue + 4096 + 131072 ) >> 13, 235); 716 i_u = (uint8_t)__MIN(abs( -1214 * p_line->i_red + -2384 * p_line->i_green + 717 3598 * p_line->i_blue + 4096 + 1048576) >> 13, 240); 718 i_v = (uint8_t)__MIN(abs( 3598 * p_line->i_red + -3013 * p_line->i_green + 719 -585 * p_line->i_blue + 4096 + 1048576) >> 13, 240); 719 YUVFromRGB( (p_line->i_red << 16) | 720 (p_line->i_green << 8) | 721 (p_line->i_blue ), 722 &i_y, &i_u, &i_v); 720 723 i_alpha = p_line->i_alpha; 721 724 … … 808 811 { 809 812 /* Every glyph can (and in fact must) have its own color */ 810 int i_red = ( p_line->p_rgb[ i ] & 0x00ff0000 ) >> 16; 811 int i_green = ( p_line->p_rgb[ i ] & 0x0000ff00 ) >> 8; 812 int i_blue = ( p_line->p_rgb[ i ] & 0x000000ff ); 813 814 i_y = (uint8_t)__MIN(abs( 2104 * i_red + 4130 * i_green + 815 802 * i_blue + 4096 + 131072 ) >> 13, 235); 816 i_u = (uint8_t)__MIN(abs( -1214 * i_red + -2384 * i_green + 817 3598 * i_blue + 4096 + 1048576) >> 13, 240); 818 i_v = (uint8_t)__MIN(abs( 3598 * i_red + -3013 * i_green + 819 -585 * i_blue + 4096 + 1048576) >> 13, 240); 813 YUVFromRGB( p_line->p_fg_rgb[ i ], &i_y, &i_u, &i_v ); 820 814 } 821 815 … … 824 818 for( x = 0; x < p_glyph->bitmap.width; x++, i_bitmap_offset++ ) 825 819 { 820 uint8_t i_y_local = i_y; 821 uint8_t i_u_local = i_u; 822 uint8_t i_v_local = i_v; 823 824 if( p_line->p_fg_bg_ratio != 0x00 ) 825 { 826 int i_split = p_glyph->bitmap.width * 827 p_line->p_fg_bg_ratio[ i ] / 0x7f; 828 829 if( x > i_split ) 830 { 831 YUVFromRGB( p_line->p_bg_rgb[ i ], 832 &i_y_local, &i_u_local, &i_v_local ); 833 } 834 } 835 826 836 if( p_glyph->bitmap.buffer[i_bitmap_offset] ) 827 837 { … … 1155 1165 #ifdef HAVE_FONTCONFIG 1156 1166 static ft_style_t *CreateStyle( char *psz_fontname, int i_font_size, 1157 int i_font_color, int i_font_alpha, vlc_bool_t b_bold,1167 uint32_t i_font_color, uint32_t i_karaoke_bg_color, vlc_bool_t b_bold, 1158 1168 vlc_bool_t b_italic, vlc_bool_t b_uline ) 1159 1169 { … … 1162 1172 if( p_style ) 1163 1173 { 1164 p_style->i_font_size = i_font_size; 1165 p_style->i_font_color = ( i_font_color & 0x00ffffff ) 1166 | (( i_font_alpha & 0xff ) << 24 ); 1167 p_style->b_italic = b_italic; 1168 p_style->b_bold = b_bold; 1169 p_style->b_underline = b_uline; 1170 /* p_style has just been malloc'ed in this function - 1171 * it CAN'T have a previous assignment, and hence we 1172 * don't need to do a free() for any previous value - 1173 * which will in fact be undefined. */ 1174 p_style->i_font_size = i_font_size; 1175 p_style->i_font_color = i_font_color; 1176 p_style->i_karaoke_bg_color = i_karaoke_bg_color; 1177 p_style->b_italic = b_italic; 1178 p_style->b_bold = b_bold; 1179 p_style->b_underline = b_uline; 1180 1174 1181 p_style->psz_fontname = strdup( psz_fontname ); 1175 1182 } … … 1207 1214 1208 1215 static int PushFont( font_stack_t **p_font, const char *psz_name, int i_size, 1209 int i_color, int i_alpha)1216 uint32_t i_color, uint32_t i_karaoke_bg_color ) 1210 1217 { 1211 1218 font_stack_t *p_new; … … 1225 1232 p_new->psz_name = NULL; 1226 1233 1227 p_new->i_size = i_size;1228 p_new->i_color = i_color;1229 p_new->i_ alpha = i_alpha;1234 p_new->i_size = i_size; 1235 p_new->i_color = i_color; 1236 p_new->i_karaoke_bg_color = i_karaoke_bg_color; 1230 1237 1231 1238 if( !*p_font ) … … 1274 1281 1275 1282 static int PeekFont( font_stack_t **p_font, char **psz_name, int *i_size, 1276 int *i_color, int *i_alpha)1283 uint32_t *i_color, uint32_t *i_karaoke_bg_color ) 1277 1284 { 1278 1285 font_stack_t *p_last; … … 1286 1293 ; 1287 1294 1288 *psz_name = p_last->psz_name;1289 *i_size = p_last->i_size;1290 *i_color = p_last->i_color;1291 *i_ alpha = p_last->i_alpha;1295 *psz_name = p_last->psz_name; 1296 *i_size = p_last->i_size; 1297 *i_color = p_last->i_color; 1298 *i_karaoke_bg_color = p_last->i_karaoke_bg_color; 1292 1299 1293 1300 return VLC_SUCCESS; … … 1355 1362 ft_style_t *p_style = NULL; 1356 1363 1357 char *psz_fontname = NULL;1358 int i_font_color = p_sys->i_font_color;1359 int i_font_alpha = 0;1360 int i_font_size = p_sys->i_font_size;1364 char *psz_fontname = NULL; 1365 uint32_t i_font_color = p_sys->i_font_color & 0x00ffffff; 1366 uint32_t i_karaoke_bg_color = i_font_color; 1367 int i_font_size = p_sys->i_font_size; 1361 1368 1362 1369 if( VLC_SUCCESS == PeekFont( p_fonts, &psz_fontname, &i_font_size, 1363 &i_font_color, &i_ font_alpha ))1370 &i_font_color, &i_karaoke_bg_color )) 1364 1371 { 1365 1372 p_style = CreateStyle( psz_fontname, i_font_size, i_font_color, 1366 i_ font_alpha, b_bold, b_italic, b_uline );1373 i_karaoke_bg_color, b_bold, b_italic, b_uline ); 1367 1374 } 1368 1375 return p_style; … … 1370 1377 1371 1378 static int RenderTag( filter_t *p_filter, FT_Face p_face, int i_font_color, 1372 vlc_bool_t b_uline, line_desc_t *p_line, 1373 uint32_t *psz_unicode, int *pi_pen_x, int i_pen_y, 1374 int *pi_start, FT_Vector *p_result ) 1379 vlc_bool_t b_uline, int i_karaoke_bgcolor, 1380 line_desc_t *p_line, uint32_t *psz_unicode, 1381 int *pi_pen_x, int i_pen_y, int *pi_start, 1382 FT_Vector *p_result ) 1375 1383 { 1376 1384 FT_BBox line; … … 1459 1467 } 1460 1468 p_line->pp_glyphs[ i ] = (FT_BitmapGlyph)tmp_glyph; 1461 p_line->p_rgb[ i ] = i_font_color & 0x00ffffff; 1469 p_line->p_fg_rgb[ i ] = i_font_color & 0x00ffffff; 1470 p_line->p_bg_rgb[ i ] = i_karaoke_bgcolor & 0x00ffffff; 1471 p_line->p_fg_bg_ratio[ i ] = 0x00; 1462 1472 1463 1473 line.xMax = p_line->p_glyph_pos[i].x + glyph_size.xMax - … … 1548 1558 font_stack_t **p_fonts ) 1549 1559 { 1550 int rv; 1551 char *psz_fontname = NULL; 1552 int i_font_color = 0xffffff; 1553 int i_font_alpha = 0; 1554 int i_font_size = 24; 1560 int rv; 1561 char *psz_fontname = NULL; 1562 uint32_t i_font_color = 0xffffff; 1563 int i_font_alpha = 0; 1564 uint32_t i_karaoke_bg_color = 0x00ffffff; 1565 int i_font_size = 24; 1555 1566 1556 1567 /* Default all attributes to the top font in the stack -- in case not … … 1561 1572 &i_font_size, 1562 1573 &i_font_color, 1563 &i_ font_alpha))1574 &i_karaoke_bg_color )) 1564 1575 { 1565 1576 psz_fontname = strdup( psz_fontname ); 1566 1577 } 1578 i_font_alpha = (i_font_color >> 24) & 0xff; 1579 i_font_color &= 0x00ffffff; 1567 1580 1568 1581 while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) 1569 1582 { 1570 char *psz_name = xml_ReaderName ( p_xml_reader );1571 char *psz_value = xml_ReaderValue ( p_xml_reader );1583 char *psz_name = xml_ReaderName( p_xml_reader ); 1584 char *psz_value = xml_ReaderValue( p_xml_reader ); 1572 1585 1573 1586 if( psz_name && psz_value ) … … 1613 1626 psz_fontname, 1614 1627 i_font_size, 1615 i_font_color,1616 i_ font_alpha);1628 (i_font_color & 0xffffff) | ((i_font_alpha & 0xff) << 24), 1629 i_karaoke_bg_color ); 1617 1630 1618 1631 free( psz_fontname ); … … 1677 1690 } 1678 1691 1679 static int ProcessNodes( filter_t *p_filter, xml_reader_t *p_xml_reader, 1680 text_style_t *p_font_style, uint32_t *psz_text, 1681 int *pi_len, uint32_t *pi_runs, 1682 uint32_t **ppi_run_lengths, ft_style_t ***ppp_styles) 1692 static void SetKaraokeLen( uint32_t i_runs, uint32_t *pi_run_lengths, 1693 uint32_t i_k_runs, uint32_t *pi_k_run_lengths ) 1694 { 1695 /* Karaoke tags _PRECEDE_ the text they specify a duration 1696 * for, therefore we are working out the length for the 1697 * previous tag, and first time through we have nothing 1698 */ 1699 if( pi_k_run_lengths ) 1700 { 1701 int i_chars = 0; 1702 uint32_t i; 1703 1704 /* Work out how many characters are presently in the string 1705 */ 1706 for( i = 0; i < i_runs; i++ ) 1707 i_chars += pi_run_lengths[ i ]; 1708 1709 /* Subtract away those we've already allocated to other 1710 * karaoke tags 1711 */ 1712 for( i = 0; i < i_k_runs; i++ ) 1713 i_chars -= pi_k_run_lengths[ i ]; 1714 1715 pi_k_run_lengths[ i_k_runs - 1 ] = i_chars; 1716 } 1717 } 1718 1719 static void SetupKaraoke( xml_reader_t *p_xml_reader, uint32_t *pi_k_runs, 1720 uint32_t **ppi_k_run_lengths, 1721 uint32_t **ppi_k_durations ) 1722 { 1723 while ( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) 1724 { 1725 char *psz_name = xml_ReaderName( p_xml_reader ); 1726 char *psz_value = xml_ReaderValue( p_xml_reader ); 1727 1728 if( psz_name && psz_value && 1729 !strcasecmp( "t", psz_name ) ) 1730 { 1731 if( ppi_k_durations && ppi_k_run_lengths ) 1732 { 1733 (*pi_k_runs)++; 1734 1735 if( *ppi_k_durations ) 1736 { 1737 *ppi_k_durations = (uint32_t *) 1738 realloc( *ppi_k_durations, 1739 *pi_k_runs * sizeof( uint32_t ) ); 1740 } 1741 else if( *pi_k_runs == 1 ) 1742 { 1743 *ppi_k_durations = (uint32_t *) 1744 malloc( *pi_k_runs * sizeof( uint32_t ) ); 1745 } 1746 1747 if( *ppi_k_run_lengths ) 1748 { 1749 *ppi_k_run_lengths = (uint32_t *) 1750 realloc( *ppi_k_run_lengths, 1751 *pi_k_runs * sizeof( uint32_t ) ); 1752 } 1753 else if( *pi_k_runs == 1 ) 1754 { 1755 *ppi_k_run_lengths = (uint32_t *) 1756 malloc( *pi_k_runs * sizeof( uint32_t ) ); 1757 } 1758 if( *ppi_k_durations ) 1759 (*ppi_k_durations)[ *pi_k_runs - 1 ] = atoi( psz_value ); 1760 1761 if( *ppi_k_run_lengths ) 1762 (*ppi_k_run_lengths)[ *pi_k_runs - 1 ] = 0; 1763 } 1764 } 1765 if( psz_name ) free( psz_name ); 1766 if( psz_value ) free( psz_value ); 1767 } 1768 } 1769 1770 static int ProcessNodes( filter_t *p_filter, 1771 xml_reader_t *p_xml_reader, 1772 text_style_t *p_font_style, 1773 uint32_t *psz_text, 1774 int *pi_len, 1775 1776 uint32_t *pi_runs, 1777 uint32_t **ppi_run_lengths, 1778 ft_style_t ***ppp_styles, 1779 1780 vlc_bool_t b_karaoke, 1781 uint32_t *pi_k_runs, 1782 uint32_t **ppi_k_run_lengths, 1783 uint32_t **ppi_k_durations ) 1683 1784 { 1684 1785 int rv = VLC_SUCCESS; … … 1696 1797 { 1697 1798 rv = PushFont( &p_fonts, 1698 p_font_style->psz_fontname, 1699 p_font_style->i_font_size, 1700 p_font_style->i_font_color, 1701 p_font_style->i_font_alpha ); 1799 p_font_style->psz_fontname, 1800 p_font_style->i_font_size, 1801 (p_font_style->i_font_color & 0xffffff) | 1802 ((p_font_style->i_font_alpha & 0xff) << 24), 1803 (p_font_style->i_karaoke_background_color & 0xffffff) | 1804 ((p_font_style->i_karaoke_background_alpha & 0xff) << 24)); 1702 1805 1703 1806 if( p_font_style->i_style_flags & STYLE_BOLD ) … … 1713 1816 FC_DEFAULT_FONT, 1714 1817 p_sys->i_font_size, 1715 0x ffffff,1716 0 );1818 0x00ffffff, 1819 0x00ffffff ); 1717 1820 } 1718 1821 if( rv != VLC_SUCCESS ) … … 1764 1867 b_uline ) ); 1765 1868 } 1869 else if( !strcasecmp( "k", psz_node ) ) 1870 { 1871 /* Only valid in karaoke */ 1872 if( b_karaoke ) 1873 { 1874 if( *pi_k_runs > 0 ) 1875 { 1876 SetKaraokeLen( *pi_runs, *ppi_run_lengths, 1877 *pi_k_runs, *ppi_k_run_lengths ); 1878 } 1879 SetupKaraoke( p_xml_reader, pi_k_runs, 1880 ppi_k_run_lengths, ppi_k_durations ); 1881 } 1882 } 1766 1883 1767 1884 free( psz_node ); … … 1803 1920 } 1804 1921 } 1922 if( b_karaoke ) 1923 { 1924 SetKaraokeLen( *pi_runs, *ppi_run_lengths, 1925 *pi_k_runs, *ppi_k_run_lengths ); 1926 } 1805 1927 1806 1928 *pi_len = psz_text - psz_text_orig; … … 1811 1933 } 1812 1934 1813 static int ProcessLines( filter_t *p_filter, uint32_t *psz_text, 1814 int i_len, uint32_t i_runs, 1815 uint32_t *pi_run_lengths, ft_style_t **pp_styles, 1816 line_desc_t **pp_lines, FT_Vector *p_result ) 1935 static int ProcessLines( filter_t *p_filter, 1936 uint32_t *psz_text, 1937 int i_len, 1938 1939 uint32_t i_runs, 1940 uint32_t *pi_run_lengths, 1941 ft_style_t **pp_styles, 1942 line_desc_t **pp_lines, 1943 1944 FT_Vector *p_result, 1945 1946 vlc_bool_t b_karaoke, 1947 uint32_t i_k_runs, 1948 uint32_t *pi_k_run_lengths, 1949 uint32_t *pi_k_durations ) 1817 1950 { 1818 1951 filter_sys_t *p_sys = p_filter->p_sys; 1819 ft_style_t **pp_char_styles; 1952 ft_style_t **pp_char_styles; 1953 int *p_new_positions = NULL; 1954 int8_t *p_levels = NULL; 1955 uint8_t *pi_karaoke_bar = NULL; 1820 1956 uint32_t i, j, k; 1821 1957 int i_prev; … … 1829 1965 return VLC_ENOMEM; 1830 1966 1967 if( b_karaoke ) 1968 { 1969 pi_karaoke_bar = (uint8_t *) malloc( i_len * sizeof( uint8_t )); 1970 /* If we can't allocate sufficient memory for karaoke, continue anyway - 1971 * we just won't be able to display the progress bar; at least we'll 1972 * get the text. 1973 */ 1974 } 1975 1831 1976 i = 0; 1832 1977 for( j = 0; j < i_runs; j++ ) … … 1837 1982 { 1838 1983 ft_style_t **pp_char_styles_new; 1839 int *p_ positions;1984 int *p_old_positions; 1840 1985 uint32_t *p_fribidi_string; 1841 1986 int start_pos, pos = 0; 1842 1987 1843 p_fribidi_string = malloc( (i_len + 1) * sizeof(uint32_t) ); 1844 if(! p_fribidi_string ) 1988 pp_char_styles_new = (ft_style_t **) 1989 malloc( i_len * sizeof( ft_style_t * )); 1990 1991 p_fribidi_string = (uint32_t *) 1992 malloc( (i_len + 1) * sizeof(uint32_t) ); 1993 p_old_positions = (int *) 1994 malloc( (i_len + 1) * sizeof( int ) ); 1995 p_new_positions = (int *) 1996 malloc( (i_len + 1) * sizeof( int ) ); 1997 p_levels = (int8_t *) 1998 malloc( (i_len + 1) * sizeof( int8_t ) ); 1999 2000 if( ! pp_char_styles_new || 2001 ! p_fribidi_string || 2002 ! p_old_positions || 2003 ! p_new_positions || 2004 ! p_levels ) 1845 2005 { 1846 2006 msg_Err( p_filter, "out of memory" ); 1847 free( pp_char_styles ); 1848 return VLC_ENOMEM; 1849 } 1850 pp_char_styles_new = (ft_style_t **) 1851 malloc( i_len * sizeof( ft_style_t * )); 1852 if(! pp_char_styles_new ) 1853 { 1854 msg_Err( p_filter, "out of memory" ); 1855 free( p_fribidi_string ); 1856 free( pp_char_styles ); 1857 return VLC_ENOMEM; 1858 } 1859 p_positions = (int *) malloc( (i_len + 1) * sizeof( int ) ); 1860 if(! p_positions ) 1861 { 1862 msg_Err( p_filter, "out of memory" ); 1863 free( pp_char_styles_new ); 1864 free( p_fribidi_string ); 2007 if( p_levels ) free( p_levels ); 2008 if( p_old_positions ) free( p_old_positions ); 2009 if( p_new_positions ) free( p_new_positions ); 2010 if( p_fribidi_string ) free( p_fribidi_string ); 2011 if( pp_char_styles_new ) free( pp_char_styles_new ); 2012 if( pi_karaoke_bar ) free( pi_karaoke_bar ); 2013 1865 2014 free( pp_char_styles ); 1866 2015 return VLC_ENOMEM; … … 1875 2024 p_fribidi_string[pos] = psz_text[pos]; 1876 2025 pp_char_styles_new[pos] = pp_char_styles[pos]; 2026 p_new_positions[pos] = pos; 2027 p_levels[pos] = 0; 1877 2028 ++pos; 1878 2029 } … … 1889 2040 pos - start_pos, &base_dir, 1890 2041 (FriBidiChar*)p_fribidi_string + start_pos, 1891 0,1892 p_ positions, 0);1893 2042 p_new_positions + start_pos, 2043 p_old_positions, 2044 p_levels + start_pos ); 1894 2045 for( j = (uint32_t) start_pos; j < (uint32_t) pos; j++ ) 1895 2046 { 1896 2047 pp_char_styles_new[ j ] = pp_char_styles[ start_pos + 1897 p_positions[ j - start_pos ] ]; 2048 p_old_positions[ j - start_pos ] ]; 2049 p_new_positions[ j ] += start_pos; 1898 2050 } 1899 2051 } 1900 2052 } 1901 free( p_ positions );2053 free( p_old_positions ); 1902 2054 free( pp_char_styles ); 1903 2055 pp_char_styles = pp_char_styles_new; … … 1906 2058 } 1907 2059 #endif 2060 /* Work out the karaoke */ 2061 if( pi_karaoke_bar ) 2062 { 2063 int64_t i_last_duration = 0; 2064 int64_t i_duration = 0; 2065 int64_t i_start_pos = 0; 2066 int64_t i_elapsed = var_GetTime( p_filter, "spu-elapsed" ) / 1000; 2067 2068 for( k = 0; k< i_k_runs; k++ ) 2069 { 2070 double fraction = 0.0; 2071 2072 i_duration += pi_k_durations[ k ]; 2073 2074 if( i_duration < i_elapsed ) 2075 { 2076 /* Completely finished this run-length - 2077 * let it render normally */ 2078 2079 fraction = 1.0; 2080 } 2081 else if( i_elapsed < i_last_duration ) 2082 { 2083 /* Haven't got up to this segment yet - 2084 * render it completely in karaoke BG mode */ 2085 2086 fraction = 0.0; 2087 } 2088 else 2089 { 2090 /* Partway through this run */ 2091 2092 fraction = (double)(i_elapsed - i_last_duration) / 2093 (double)pi_k_durations[ k ]; 2094 } 2095 for( i = 0; i < pi_k_run_lengths[ k ]; i++ ) 2096 { 2097 double shade = pi_k_run_lengths[ k ] * fraction; 2098 2099 if( p_new_positions ) 2100 j = p_new_positions[ i_start_pos + i ]; 2101 else 2102 j = i_start_pos + i; 2103 2104 if( i < (uint32_t)shade ) 2105 pi_karaoke_bar[ j ] = 0xff; 2106 else if( (double)i > shade ) 2107 pi_karaoke_bar[ j ] = 0x00; 2108 else 2109 { 2110 shade -= (int)shade; 2111 pi_karaoke_bar[ j ] = ((int)(shade * 128.0) & 0x7f) | 2112 ((p_levels ? (p_levels[ j ] % 2) : 0 ) << 7); 2113 } 2114 } 2115 2116 i_last_duration = i_duration; 2117 i_start_pos += pi_k_run_lengths[ k ]; 2118 } 2119 } 2120 if( p_levels ) free( p_levels ); 2121 if( p_new_positions ) free( p_new_positions ); 2122 1908 2123 FT_Vector tmp_result; 1909 2124 … … 1945 2160 free( psz_text ); 1946 2161 #endif 2162 if( pi_karaoke_bar ) 2163 free( pi_karaoke_bar ); 1947 2164 return VLC_EGENERIC; 1948 2165 } … … 1960 2177 free( psz_text ); 1961 2178 #endif 2179 if( pi_karaoke_bar ) 2180 free( pi_karaoke_bar ); 1962 2181 return VLC_EGENERIC; 1963 2182 } … … 1977 2196 free( psz_text ); 1978 2197 #endif 2198 if( pi_karaoke_bar ) 2199 free( pi_karaoke_bar ); 1979 2200 return VLC_ENOMEM; 1980 2201 } … … 1995 2216 free( psz_text ); 1996 2217 #endif 2218 if( pi_karaoke_bar ) 2219 free( pi_karaoke_bar ); 1997 2220 return VLC_ENOMEM; 1998 2221 } … … 2015 2238 else *pp_lines = p_line; 2016 2239 } 2240 2017 2241 if( RenderTag( p_filter, p_face ? p_face : p_sys->p_face, 2018 2242 p_style->i_font_color, p_style->b_underline, 2243 p_style->i_karaoke_bg_color, 2019 2244 p_line, psz_unicode, &i_pen_x, i_pen_y, &i_posn, 2020 2245 &tmp_result ) != VLC_SUCCESS ) … … 2026 2251 free( psz_text ); 2027 2252 #endif 2253 if( pi_karaoke_bar ) 2254 free( pi_karaoke_bar ); 2028 2255 return VLC_EGENERIC; 2029 2256 } 2257 2030 2258 if( *psz_unicode ) 2031 2259 { … … 2046 2274 free( psz_text ); 2047 2275 #endif 2048 2049 2276 if( p_line ) 2050 2277 { … … 2052 2279 p_result->y += tmp_result.y; 2053 2280 } 2281 2282 if( pi_karaoke_bar ) 2283 { 2284 int i = 0; 2285 for( p_line = *pp_lines; p_line; p_line=p_line->p_next ) 2286 { 2287 for( k = 0; p_line->pp_glyphs[ k ]; k++, i++ ) 2288 { 2289 if( (pi_karaoke_bar[ i ] & 0x7f) == 0x7f) 2290 { 2291 /* do nothing */ 2292 } 2293 else if( (pi_karaoke_bar[ i ] & 0x7f) == 0x00) 2294 { 2295 /* 100% BG colour will render faster if we 2296 * instead make it 100% FG colour, so leave 2297 * the ratio alone and copy the value across 2298 */ 2299 p_line->p_fg_rgb[ k ] = p_line->p_bg_rgb[ k ]; 2300 } 2301 else 2302 { 2303 if( pi_karaoke_bar[ i ] & 0x80 ) 2304 { 2305 /* Swap Left and Right sides over for Right aligned 2306 * language text (eg. Arabic, Hebrew) 2307 */ 2308 uint32_t i_tmp = p_line->p_fg_rgb[ k ]; 2309 2310 p_line->p_fg_rgb[ k ] = p_line->p_bg_rgb[ k ]; 2311 p_line->p_bg_rgb[ k ] = i_tmp; 2312 } 2313 p_line->p_fg_bg_ratio[ k ] = (pi_karaoke_bar[ i ] & 0x7f); 2314 } 2315 } 2316 /* Jump over the '\n' at the line-end */ 2317 i++; 2318 } 2319 free( pi_karaoke_bar ); 2320 } 2321 2054 2322 return VLC_SUCCESS; 2055 2323 } … … 2075 2343 if( p_xml ) 2076 2344 { 2345 vlc_bool_t b_karaoke = VLC_FALSE; 2346 2077 2347 p_xml_reader = xml_ReaderCreate( p_xml, p_sub ); 2348 if( p_xml_reader ) 2349 { 2350 /* Look for Root Node */ 2351 if( xml_ReaderRead( p_xml_reader ) == 1 ) 2352 { 2353 char *psz_node = xml_ReaderName( p_xml_reader ); 2354 2355 if( !strcasecmp( "karaoke", psz_node ) ) 2356 { 2357 /* We're going to have to render the text a number 2358 * of times to show the progress marker on the text. 2359 */ 2360 var_SetBool( p_filter, "text-rerender", VLC_TRUE ); 2361 b_karaoke = VLC_TRUE; 2362 } 2363 else if( !strcasecmp( "text", psz_node ) ) 2364 { 2365 b_karaoke = VLC_FALSE; 2366 } 2367 else 2368 { 2369 /* Only text and karaoke tags are supported */ 2370 xml_ReaderDelete( p_xml, p_xml_reader ); 2371 p_xml_reader = NULL; 2372 rv = VLC_EGENERIC; 2373 } 2374 2375 free( psz_node ); 2376 } 2377 } 2378 2078 2379 if( p_xml_reader ) 2079 2380 { … … 2081 2382 int i_len; 2082 2383 uint32_t i_runs = 0; 2384 uint32_t i_k_runs = 0; 2083 2385 uint32_t *pi_run_lengths = NULL; 2386 uint32_t *pi_k_run_lengths = NULL; 2387 uint32_t *pi_k_durations = NULL; 2084 2388 ft_style_t **pp_styles = NULL; 2085 2389 FT_Vector result; … … 2094 2398 rv = ProcessNodes( p_filter, p_xml_reader, 2095 2399 p_region_in->p_style, psz_text, &i_len, 2096 &i_runs, &pi_run_lengths, &pp_styles ); 2400 &i_runs, &pi_run_lengths, &pp_styles, 2401 b_karaoke, &i_k_runs, &pi_k_run_lengths, 2402 &pi_k_durations ); 2097 2403 2098 2404 p_region_out->i_x = p_region_in->i_x; … … 2102 2408 { 2103 2409 rv = ProcessLines( p_filter, psz_text, i_len, i_runs, 2104 pi_run_lengths, pp_styles, &p_lines, &result ); 2410 pi_run_lengths, pp_styles, &p_lines, &result, 2411 b_karaoke, i_k_runs, pi_k_run_lengths, 2412 pi_k_durations ); 2105 2413 } 2106 2414 … … 2212 2520 free( p_line->pp_glyphs ); 2213 2521 free( p_line->p_glyph_pos ); 2214 free( p_line->p_rgb ); 2522 free( p_line->p_fg_rgb ); 2523 free( p_line->p_bg_rgb ); 2524 free( p_line->p_fg_bg_ratio ); 2215 2525 free( p_line->pi_underline_offset ); 2216 2526 free( p_line->pi_underline_thickness ); … … 2242 2552 p_line->pp_glyphs = malloc( sizeof(FT_BitmapGlyph) * ( i_count + 1 ) ); 2243 2553 p_line->p_glyph_pos = malloc( sizeof( FT_Vector ) * ( i_count + 1 ) ); 2244 p_line->p_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); 2554 p_line->p_fg_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); 2555 p_line->p_bg_rgb = malloc( sizeof( uint32_t ) * ( i_count + 1 ) ); 2556 p_line->p_fg_bg_ratio = calloc( i_count + 1, sizeof( uint8_t ) ); 2245 2557 p_line->pi_underline_offset = calloc( i_count + 1, sizeof( uint16_t ) ); 2246 2558 p_line->pi_underline_thickness = calloc( i_count + 1, sizeof( uint16_t ) ); 2247 2559 if( ( p_line->pp_glyphs == NULL ) || 2248 2560 ( p_line->p_glyph_pos == NULL ) || 2249 ( p_line->p_rgb == NULL ) || 2561 ( p_line->p_fg_rgb == NULL ) || 2562 ( p_line->p_bg_rgb == NULL ) || 2563 ( p_line->p_fg_bg_ratio == NULL ) || 2250 2564 ( p_line->pi_underline_offset == NULL ) || 2251 2565 ( p_line->pi_underline_thickness == NULL ) ) … … 2254 2568 free( p_line->pi_underline_thickness ); 2255 2569 if( p_line->pi_underline_offset ) free( p_line->pi_underline_offset ); 2256 if( p_line->p_rgb ) free( p_line->p_rgb ); 2570 if( p_line->p_fg_rgb ) free( p_line->p_fg_rgb ); 2571 if( p_line->p_bg_rgb ) free( p_line->p_bg_rgb ); 2572 if( p_line->p_fg_bg_ratio ) free( p_line->p_fg_bg_ratio ); 2257 2573 if( p_line->p_glyph_pos ) free( p_line->p_glyph_pos ); 2258 2574 if( p_line->pp_glyphs ) free( p_line->pp_glyphs ); … … 2310 2626 return VLC_SUCCESS; 2311 2627 } 2628 2629 static void YUVFromRGB( uint32_t i_argb, 2630 uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v ) 2631 { 2632 int i_red = ( i_argb & 0x00ff0000 ) >> 16; 2633 int i_green = ( i_argb & 0x0000ff00 ) >> 8; 2634 int i_blue = ( i_argb & 0x000000ff ); 2635 2636 *pi_y = (uint8_t)__MIN(abs( 2104 * i_red + 4130 * i_green + 2637 802 * i_blue + 4096 + 131072 ) >> 13, 235); 2638 *pi_u = (uint8_t)__MIN(abs( -1214 * i_red + -2384 * i_green + 2639 3598 * i_blue + 4096 + 1048576) >> 13, 240); 2640 *pi_v = (uint8_t)__MIN(abs( 3598 * i_red + -3013 * i_green + 2641 -585 * i_blue + 4096 + 1048576) >> 13, 240); 2642 }
