[vlc-commits] freetype: blending: refactor and improve speed
Francois Cartegnie
git at videolan.org
Thu Sep 3 21:30:22 CEST 2020
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Aug 27 14:39:11 2020 +0200| [b508504e6dd92064397b6c7ff0375e760a7bfbd5] | committer: Francois Cartegnie
freetype: blending: refactor and improve speed
webvtt_css_family_fallback_mono.mkv
with forced non zero background
32% less instr for RGBA/YUVA
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b508504e6dd92064397b6c7ff0375e760a7bfbd5
---
modules/text_renderer/Makefile.am | 5 +-
modules/text_renderer/freetype/blend/blend.h | 83 ++++++++
modules/text_renderer/freetype/blend/rgb.h | 109 ++++++++++
modules/text_renderer/freetype/blend/yuv.h | 103 ++++++++++
modules/text_renderer/freetype/freetype.c | 294 +++++----------------------
5 files changed, 345 insertions(+), 249 deletions(-)
diff --git a/modules/text_renderer/Makefile.am b/modules/text_renderer/Makefile.am
index 1d87479c59..5e29e3c116 100644
--- a/modules/text_renderer/Makefile.am
+++ b/modules/text_renderer/Makefile.am
@@ -9,7 +9,10 @@ libfreetype_plugin_la_SOURCES = \
text_renderer/freetype/ftcache.c text_renderer/freetype/ftcache.h \
text_renderer/freetype/text_layout.c text_renderer/freetype/text_layout.h \
text_renderer/freetype/lru.c text_renderer/freetype/lru.h \
- text_renderer/freetype/fonts/backends.h
+ text_renderer/freetype/fonts/backends.h \
+ text_renderer/freetype/blend/blend.h \
+ text_renderer/freetype/blend/rgb.h \
+ text_renderer/freetype/blend/yuv.h
libfreetype_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(FREETYPE_CFLAGS)
libfreetype_plugin_la_LIBADD = $(AM_LIBADD) $(LIBM)
diff --git a/modules/text_renderer/freetype/blend/blend.h b/modules/text_renderer/freetype/blend/blend.h
new file mode 100644
index 0000000000..93e97ff840
--- /dev/null
+++ b/modules/text_renderer/freetype/blend/blend.h
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * blend.h :
+ *****************************************************************************
+ * Copyright (C) 2002 - 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef VLC_FREETYPE_BLEND_H
+#define VLC_FREETYPE_BLEND_H
+
+typedef void (*ft_glyph_blender)( picture_t *, int, int,
+ int, int, int, int, FT_BitmapGlyph );
+typedef void (*ft_surface_filler)( picture_t *, int, int, int, int,
+ int, int, int, int);
+typedef void (*ft_components_extractor)( uint32_t, uint8_t *, uint8_t *, uint8_t * );
+
+typedef struct
+{
+ ft_components_extractor extract;
+ ft_surface_filler fill;
+ ft_glyph_blender blend;
+} ft_drawing_functions;
+
+#define DECL_PIXEL_BLENDER( name, APOS, XPOS, YPOS, ZPOS, APLANE, XPLANE, YPLANE, ZPLANE ) \
+static inline void Blend##name##Pixel( uint8_t **dst, int a, int x, int y, int z, int glyph_a )\
+{\
+ if( glyph_a == 0 )\
+ return;\
+\
+ int i_an = a * glyph_a / 255;\
+\
+ int i_ao = dst[APLANE][APOS];\
+ if( i_ao == 0 )\
+ {\
+ dst[XPLANE][XPOS] = x;\
+ dst[YPLANE][YPOS] = y;\
+ dst[ZPLANE][ZPOS] = z;\
+ dst[APLANE][APOS] = i_an;\
+ }\
+ else\
+ {\
+ int i_ani = 255 - i_an;\
+ dst[APLANE][APOS] = 255 - (255 - i_ao) * i_ani / 255;\
+ if( dst[APLANE][APOS] != 0 )\
+ {\
+ int i_aoni = i_ao * i_ani / 255;\
+ dst[XPLANE][XPOS] = ( dst[XPLANE][XPOS] * i_aoni + x * i_an ) / dst[APLANE][APOS];\
+ dst[YPLANE][YPOS] = ( dst[YPLANE][YPOS] * i_aoni + y * i_an ) / dst[APLANE][APOS];\
+ dst[ZPLANE][ZPOS] = ( dst[ZPLANE][ZPOS] * i_aoni + z * i_an ) / dst[APLANE][APOS];\
+ }\
+ }\
+}
+
+static void BlendAXYZLine( picture_t *p_picture,
+ int i_picture_x, int i_picture_y,
+ int i_a, int i_x, int i_y, int i_z,
+ const line_character_t *p_current,
+ const line_character_t *p_next,
+ ft_drawing_functions draw )
+{
+ int i_line_width = p_current->p_glyph->bitmap.width;
+ if( p_next )
+ i_line_width = p_next->p_glyph->left - p_current->p_glyph->left;
+
+ draw.fill( p_picture,
+ i_a, i_x, i_y, i_z,
+ i_picture_x, i_picture_y + p_current->i_line_offset,
+ i_line_width, p_current->i_line_thickness );
+}
+
+#endif // VLC_FREETYPE_BLEND_H
diff --git a/modules/text_renderer/freetype/blend/rgb.h b/modules/text_renderer/freetype/blend/rgb.h
new file mode 100644
index 0000000000..f3d9c45706
--- /dev/null
+++ b/modules/text_renderer/freetype/blend/rgb.h
@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * rgb.h :
+ *****************************************************************************
+ * Copyright (C) 2002 - 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include "blend.h"
+
+static void RGBFromRGB( uint32_t i_argb,
+ uint8_t *pi_r, uint8_t *pi_g, uint8_t *pi_b )
+{
+ *pi_r = ( i_argb & 0x00ff0000 ) >> 16;
+ *pi_g = ( i_argb & 0x0000ff00 ) >> 8;
+ *pi_b = ( i_argb & 0x000000ff );
+}
+
+#define DECL_RGB_FILLER( name, APOS, XPOS, YPOS, ZPOS ) \
+static void Fill##name##Picture( picture_t *p_picture,\
+ int a, int r, int g, int b,\
+ int x, int y, int w, int h )\
+{\
+ uint8_t *row = &p_picture->p[0].p_pixels[y * p_picture->p->i_pitch + x * 4];\
+\
+ if (unlikely(a == 0 || (a == r && b == g && r == g)))\
+ { /* fast path */\
+ memset(row, a, h * p_picture->p[0].i_pitch);\
+ return;\
+ }\
+\
+ for( int dy = 0; dy < h; dy++ )\
+ {\
+ uint8_t *p = row;\
+ for( int dx = 0; dx < w; dx++ )\
+ {\
+ p[XPOS] = r;\
+ p[YPOS] = g;\
+ p[ZPOS] = b;\
+ p[APOS] = a;\
+ p += 4;\
+ }\
+ row += p_picture->p->i_pitch;\
+ }\
+}
+
+DECL_RGB_FILLER( RGBA, 3, 0, 1, 2 );
+DECL_PIXEL_BLENDER(RGBA, 3, 0, 1, 2, 0, 0, 0, 0);
+
+DECL_RGB_FILLER( ARGB, 0, 1, 2, 3 );
+DECL_PIXEL_BLENDER(ARGB, 0, 1, 2, 3, 0, 0, 0, 0);
+
+#undef DECL_RGB_FILLER
+
+static inline void BlendGlyphToRGB( picture_t *p_picture,
+ int i_picture_x, int i_picture_y,
+ int i_a, int i_x, int i_y, int i_z,
+ FT_BitmapGlyph p_glyph,
+ void (*BlendPixel)( uint8_t **, int, int, int, int, int ) )
+{
+ const uint8_t *srcrow = p_glyph->bitmap.buffer;
+ int i_pitch_src = p_glyph->bitmap.pitch;
+ int i_pitch_dst = p_picture->p[0].i_pitch;
+ uint8_t *dstrow = &p_picture->p[0].p_pixels[i_picture_y * i_pitch_dst + 4 * i_picture_x];
+
+ for( unsigned int dy = 0; dy < p_glyph->bitmap.rows; dy++ )
+ {
+ const uint8_t *src = srcrow;
+ uint8_t *dst = dstrow;
+ for( unsigned int dx = 0; dx < p_glyph->bitmap.width; dx++ )
+ {
+ BlendPixel( &dst, i_a, i_x, i_y, i_z, *src++ );
+ dst += 4;
+ }
+ srcrow += i_pitch_src;
+ dstrow += i_pitch_dst;
+ }
+}
+
+static void BlendGlyphToRGBA( picture_t *p_picture,
+ int i_picture_x, int i_picture_y,
+ int i_a, int i_x, int i_y, int i_z,
+ FT_BitmapGlyph p_glyph )
+{
+ BlendGlyphToRGB( p_picture, i_picture_x, i_picture_y,
+ i_a, i_x, i_y, i_z, p_glyph,
+ BlendRGBAPixel );
+}
+
+static void BlendGlyphToARGB( picture_t *p_picture,
+ int i_picture_x, int i_picture_y,
+ int i_a, int i_x, int i_y, int i_z,
+ FT_BitmapGlyph p_glyph )
+{
+ BlendGlyphToRGB( p_picture, i_picture_x, i_picture_y,
+ i_a, i_x, i_y, i_z, p_glyph,
+ BlendARGBPixel );
+}
diff --git a/modules/text_renderer/freetype/blend/yuv.h b/modules/text_renderer/freetype/blend/yuv.h
new file mode 100644
index 0000000000..30fc134b18
--- /dev/null
+++ b/modules/text_renderer/freetype/blend/yuv.h
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * yuv.h :
+ *****************************************************************************
+ * Copyright (C) 2002 - 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include "blend.h"
+
+static void YUVFromRGB( uint32_t i_argb,
+ uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v )
+{
+ int i_red = ( i_argb & 0x00ff0000 ) >> 16;
+ int i_green = ( i_argb & 0x0000ff00 ) >> 8;
+ int i_blue = ( i_argb & 0x000000ff );
+
+ /* 18.13 fixed point of
+ Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
+ Cb = U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
+ Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 */
+ uint8_t y = abs( 2104 * i_red + 4130 * i_green +
+ 802 * i_blue + 4096 + 131072 ) >> 13;
+ uint8_t u = abs( -1214 * i_red + -2384 * i_green +
+ 3598 * i_blue + 4096 + 1048576) >> 13;
+ uint8_t v = abs( 3598 * i_red + -3013 * i_green +
+ -585 * i_blue + 4096 + 1048576) >> 13;
+ *pi_y = __MIN(y, 235);
+ *pi_u = __MIN(u, 240);
+ *pi_v = __MIN(v, 240);
+}
+
+static void FillYUVAPicture( picture_t *p_picture,
+ int i_a, int i_y, int i_u, int i_v,
+ int x, int y, int w, int h )
+{
+ int values[4] = { i_y, i_u, i_v, i_a };
+ for( int i = 0; i < 4; i++ )
+ {
+ plane_t *plane = &p_picture->p[i];
+ uint8_t *row = &plane->p_pixels[y * p_picture->p->i_pitch +
+ x * plane->i_pixel_pitch];
+ for( int dy = 0; dy < h; dy++ )
+ {
+ memset( row, values[i], plane->i_pixel_pitch * w );
+ row += p_picture->p->i_pitch;
+ }
+ }
+}
+
+DECL_PIXEL_BLENDER(YUVA, 0, 0, 0, 0, A_PLANE, Y_PLANE, U_PLANE, V_PLANE);
+
+static void BlendGlyphToYUVA( picture_t *p_picture,
+ int i_picture_x, int i_picture_y,
+ int i_a, int i_x, int i_y, int i_z,
+ FT_BitmapGlyph p_glyph )
+{
+ const uint8_t *srcrow = p_glyph->bitmap.buffer;
+ int i_pitch_src = p_glyph->bitmap.pitch;
+
+ uint8_t *dstrows[4];
+ dstrows[0] = &p_picture->p[0].p_pixels[i_picture_y * p_picture->p[0].i_pitch +
+ i_picture_x * p_picture->p[0].i_pixel_pitch];
+ dstrows[1] = &p_picture->p[1].p_pixels[i_picture_y * p_picture->p[1].i_pitch +
+ i_picture_x * p_picture->p[1].i_pixel_pitch];
+ dstrows[2] = &p_picture->p[2].p_pixels[i_picture_y * p_picture->p[2].i_pitch +
+ i_picture_x * p_picture->p[2].i_pixel_pitch];
+ dstrows[3] = &p_picture->p[3].p_pixels[i_picture_y * p_picture->p[3].i_pitch +
+ i_picture_x * p_picture->p[3].i_pixel_pitch];
+
+ for( unsigned int dy = 0; dy < p_glyph->bitmap.rows; dy++ )
+ {
+ const uint8_t *src = srcrow;
+
+ uint8_t *dst[4];
+ memcpy(dst, dstrows, 4 * sizeof(dst[0]));
+ for( unsigned int dx = 0; dx < p_glyph->bitmap.width; dx++ )
+ {
+ BlendYUVAPixel( dst, i_a, i_x, i_y, i_z, *src++ );
+ dst[0] += p_picture->p[0].i_pixel_pitch;
+ dst[1] += p_picture->p[1].i_pixel_pitch;
+ dst[2] += p_picture->p[2].i_pixel_pitch;
+ dst[3] += p_picture->p[3].i_pixel_pitch;
+ }
+
+ srcrow += i_pitch_src;
+ dstrows[0] += p_picture->p[0].i_pitch;
+ dstrows[1] += p_picture->p[1].i_pitch;
+ dstrows[2] += p_picture->p[2].i_pitch;
+ dstrows[3] += p_picture->p[3].i_pitch;
+ }
+}
diff --git a/modules/text_renderer/freetype/freetype.c b/modules/text_renderer/freetype/freetype.c
index 2ecddc56b0..5b5fc2d08f 100644
--- a/modules/text_renderer/freetype/freetype.c
+++ b/modules/text_renderer/freetype/freetype.c
@@ -47,6 +47,8 @@
#include "platform_fonts.h"
#include "freetype.h"
#include "text_layout.h"
+#include "blend/rgb.h"
+#include "blend/yuv.h"
/*****************************************************************************
* Module descriptor
@@ -208,27 +210,6 @@ vlc_module_begin ()
vlc_module_end ()
/* */
-static void YUVFromRGB( uint32_t i_argb,
- uint8_t *pi_y, uint8_t *pi_u, uint8_t *pi_v )
-{
- int i_red = ( i_argb & 0x00ff0000 ) >> 16;
- int i_green = ( i_argb & 0x0000ff00 ) >> 8;
- int i_blue = ( i_argb & 0x000000ff );
-
- *pi_y = (uint8_t)__MIN(abs( 2104 * i_red + 4130 * i_green +
- 802 * i_blue + 4096 + 131072 ) >> 13, 235);
- *pi_u = (uint8_t)__MIN(abs( -1214 * i_red + -2384 * i_green +
- 3598 * i_blue + 4096 + 1048576) >> 13, 240);
- *pi_v = (uint8_t)__MIN(abs( 3598 * i_red + -3013 * i_green +
- -585 * i_blue + 4096 + 1048576) >> 13, 240);
-}
-static void RGBFromRGB( uint32_t i_argb,
- uint8_t *pi_r, uint8_t *pi_g, uint8_t *pi_b )
-{
- *pi_r = ( i_argb & 0x00ff0000 ) >> 16;
- *pi_g = ( i_argb & 0x0000ff00 ) >> 8;
- *pi_b = ( i_argb & 0x000000ff );
-}
static FT_Vector GetAlignedOffset( const line_desc_t *p_line,
const FT_BBox *p_textbbox,
@@ -494,204 +475,14 @@ static int RenderYUVP( filter_t *p_filter, subpicture_region_t *p_region,
*****************************************************************************
* This function merges the previously rendered freetype glyphs into a picture
*****************************************************************************/
-static void FillYUVAPicture( picture_t *p_picture,
- int i_a, int i_y, int i_u, int i_v )
-{
- memset( p_picture->p[0].p_pixels, i_y,
- p_picture->p[0].i_pitch * p_picture->p[0].i_lines );
- memset( p_picture->p[1].p_pixels, i_u,
- p_picture->p[1].i_pitch * p_picture->p[1].i_lines );
- memset( p_picture->p[2].p_pixels, i_v,
- p_picture->p[2].i_pitch * p_picture->p[2].i_lines );
- memset( p_picture->p[3].p_pixels, i_a,
- p_picture->p[3].i_pitch * p_picture->p[3].i_lines );
-}
-
-static inline void BlendYUVAPixel( picture_t *p_picture,
- int i_picture_x, int i_picture_y,
- int i_a, int i_y, int i_u, int i_v,
- int i_alpha )
-{
- if( i_alpha == 0 )
- return;
-
- int i_an = i_a * i_alpha / 255;
-
- uint8_t *p_y = &p_picture->p[0].p_pixels[i_picture_y * p_picture->p[0].i_pitch + i_picture_x];
- uint8_t *p_u = &p_picture->p[1].p_pixels[i_picture_y * p_picture->p[1].i_pitch + i_picture_x];
- uint8_t *p_v = &p_picture->p[2].p_pixels[i_picture_y * p_picture->p[2].i_pitch + i_picture_x];
- uint8_t *p_a = &p_picture->p[3].p_pixels[i_picture_y * p_picture->p[3].i_pitch + i_picture_x];
-
- int i_ao = *p_a;
- if( i_ao == 0 )
- {
- *p_y = i_y;
- *p_u = i_u;
- *p_v = i_v;
- *p_a = i_an;
- }
- else
- {
- int i_ani = 255 - i_an;
- int i_aoni = i_ao * i_ani / 255;
- *p_a = 255 - (255 - *p_a) * i_ani / 255;
- if( *p_a != 0 )
- {
- *p_y = ( *p_y * i_aoni + i_y * i_an ) / *p_a;
- *p_u = ( *p_u * i_aoni + i_u * i_an ) / *p_a;
- *p_v = ( *p_v * i_aoni + i_v * i_an ) / *p_a;
- }
- }
-}
-
-static void FillRGBAPicture( picture_t *p_picture,
- int i_a, int i_r, int i_g, int i_b )
-{
- for( int dy = 0; dy < p_picture->p[0].i_visible_lines; dy++ )
- {
- for( int dx = 0; dx < p_picture->p[0].i_visible_pitch; dx += 4 )
- {
- uint8_t *p_rgba = &p_picture->p->p_pixels[dy * p_picture->p->i_pitch + dx];
- p_rgba[0] = i_r;
- p_rgba[1] = i_g;
- p_rgba[2] = i_b;
- p_rgba[3] = i_a;
- }
- }
-}
-
-static inline void BlendRGBAPixel( picture_t *p_picture,
- int i_picture_x, int i_picture_y,
- int i_a, int i_r, int i_g, int i_b,
- int i_alpha )
-{
- if( i_alpha == 0 )
- return;
-
- int i_an = i_a * i_alpha / 255;
-
- uint8_t *p_rgba = &p_picture->p->p_pixels[i_picture_y * p_picture->p->i_pitch + 4 * i_picture_x];
-
- int i_ao = p_rgba[3];
- if( i_ao == 0 )
- {
- p_rgba[0] = i_r;
- p_rgba[1] = i_g;
- p_rgba[2] = i_b;
- p_rgba[3] = i_an;
- }
- else
- {
- int i_ani = 255 - i_an;
- p_rgba[3] = 255 - (255 - p_rgba[3]) * i_ani / 255;
- if( p_rgba[3] != 0 )
- {
- int i_aoni = i_ao * i_ani / 255;
- p_rgba[0] = ( p_rgba[0] * i_aoni + i_r * i_an ) / p_rgba[3];
- p_rgba[1] = ( p_rgba[1] * i_aoni + i_g * i_an ) / p_rgba[3];
- p_rgba[2] = ( p_rgba[2] * i_aoni + i_b * i_an ) / p_rgba[3];
- }
- }
-}
-
-static void FillARGBPicture(picture_t *pic, int a, int r, int g, int b)
-{
- if (a == 0)
- r = g = b = 0;
- if (a == r && a == b && a == g)
- { /* fast path */
- memset(pic->p->p_pixels, a, pic->p->i_visible_lines * pic->p->i_pitch);
- return;
- }
-
- uint_fast32_t pixel = VLC_FOURCC(a, r, g, b);
- uint8_t *line = pic->p->p_pixels;
-
- for (unsigned lines = pic->p->i_visible_lines; lines > 0; lines--)
- {
- uint32_t *pixels = (uint32_t *)line;
- for (unsigned cols = pic->p->i_visible_pitch; cols > 0; cols -= 4)
- *(pixels++) = pixel;
- line += pic->p->i_pitch;
- }
-}
-
-static inline void BlendARGBPixel(picture_t *pic, int pic_x, int pic_y,
- int a, int r, int g, int b, int alpha)
-{
- if (alpha == 0)
- return;
-
- uint8_t *rgba = &pic->p->p_pixels[pic_y * pic->p->i_pitch + 4 * pic_x];
- int an = a * alpha / 255;
- int ao = rgba[3];
-
- if (ao == 0)
- {
- rgba[0] = an;
- rgba[1] = r;
- rgba[2] = g;
- rgba[3] = b;
- }
- else
- {
- int ani = 255 - an;
- rgba[0] = 255 - (255 - rgba[0]) * ani / 255;
- if (rgba[0] != 0)
- {
- int aoni = ao * ani / 255;
- rgba[1] = (rgba[1] * aoni + r * an ) / rgba[0];
- rgba[2] = (rgba[2] * aoni + g * an ) / rgba[0];
- rgba[3] = (rgba[3] * aoni + b * an ) / rgba[0];
- }
- }
-}
-
-static inline void BlendAXYZGlyph( picture_t *p_picture,
- int i_picture_x, int i_picture_y,
- int i_a, int i_x, int i_y, int i_z,
- FT_BitmapGlyph p_glyph,
- void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) )
-
-{
- for( unsigned int dy = 0; dy < p_glyph->bitmap.rows; dy++ )
- {
- for( unsigned int dx = 0; dx < p_glyph->bitmap.width; dx++ )
- BlendPixel( p_picture, i_picture_x + dx, i_picture_y + dy,
- i_a, i_x, i_y, i_z,
- p_glyph->bitmap.buffer[dy * p_glyph->bitmap.pitch + dx] );
- }
-}
-
-static inline void BlendAXYZLine( picture_t *p_picture,
- int i_picture_x, int i_picture_y,
- int i_a, int i_x, int i_y, int i_z,
- const line_character_t *p_current,
- const line_character_t *p_next,
- void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) )
-{
- int i_line_width = p_current->p_glyph->bitmap.width;
- if( p_next )
- i_line_width = p_next->p_glyph->left - p_current->p_glyph->left;
- for( int dx = 0; dx < i_line_width; dx++ )
- {
- for( int dy = 0; dy < p_current->i_line_thickness; dy++ )
- BlendPixel( p_picture,
- i_picture_x + dx,
- i_picture_y + p_current->i_line_offset + dy,
- i_a, i_x, i_y, i_z, 0xff );
- }
-}
-
-static inline void RenderBackground( subpicture_region_t *p_region,
+static 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_drawing_functions draw )
{
for( const line_desc_t *p_line = p_line_head; p_line != NULL; p_line = p_line->p_next )
{
@@ -749,8 +540,8 @@ static inline void RenderBackground( subpicture_region_t *p_region,
if( p_char->p_style->i_style_flags & STYLE_BACKGROUND )
{
uint8_t i_x, i_y, i_z;
- ExtractComponents( p_char->p_style->i_background_color,
- &i_x, &i_y, &i_z );
+ draw.extract( p_char->p_style->i_background_color,
+ &i_x, &i_y, &i_z );
const uint8_t i_alpha = p_char->p_style->i_background_alpha;
/* Render the actual background */
@@ -767,11 +558,9 @@ static inline void RenderBackground( subpicture_region_t *p_region,
.yMax = __MAX(0, p_regionbbox->yMax - segmentbgbox.yMax),
};
- for( int dy = absbox.yMax; dy < absbox.yMin; dy++ )
- {
- for( int dx = absbox.xMin; dx < absbox.xMax; dx++ )
- BlendPixel( p_picture, dx, dy, i_alpha, i_x, i_y, i_z, 0xff );
- }
+ draw.fill( p_picture, i_alpha, i_x, i_y, i_z,
+ absbox.xMin, absbox.yMax,
+ absbox.xMax - absbox.xMin, absbox.yMin - absbox.yMax );
}
}
@@ -789,8 +578,7 @@ static void RenderCharAXYZ( filter_t *p_filter,
int i_offset_x,
int i_offset_y,
int g,
- void (*ExtractComponents)( uint32_t, uint8_t *, uint8_t *, uint8_t * ),
- void (*BlendPixel)(picture_t *, int, int, int, int, int, int, int) )
+ ft_drawing_functions draw )
{
VLC_UNUSED(p_filter);
/* Render all glyphs and underline/strikethrough */
@@ -827,8 +615,7 @@ static void RenderCharAXYZ( filter_t *p_filter,
i_offset_x + p_rubydesc->origin.x,
i_offset_y - p_rubydesc->origin.y,
2,
- ExtractComponents,
- BlendPixel );
+ draw );
}
/* Don't render if invisible or not wanted */
@@ -839,16 +626,13 @@ static void RenderCharAXYZ( filter_t *p_filter,
continue;
uint8_t i_x, i_y, i_z;
- ExtractComponents( i_color, &i_x, &i_y, &i_z );
+ draw.extract( i_color, &i_x, &i_y, &i_z );
int i_glyph_y = i_offset_y - p_glyph->top;
int i_glyph_x = i_offset_x + p_glyph->left;
- BlendAXYZGlyph( p_picture,
- i_glyph_x, i_glyph_y,
- i_a, i_x, i_y, i_z,
- p_glyph,
- BlendPixel );
+ draw.blend( p_picture, i_glyph_x, i_glyph_y,
+ i_a, i_x, i_y, i_z, p_glyph );
/* underline/strikethrough are only rendered for the normal glyph */
if( g == 2 && ch->i_line_thickness > 0 )
@@ -857,7 +641,7 @@ static void RenderCharAXYZ( filter_t *p_filter,
i_a, i_x, i_y, i_z,
&ch[0],
i + 1 < p_line->i_character_count ? &ch[1] : NULL,
- BlendPixel );
+ draw );
}
}
@@ -869,9 +653,7 @@ static inline int RenderAXYZ( filter_t *p_filter,
FT_BBox *p_textbbox,
vlc_fourcc_t i_chroma,
const video_format_t *fmt_out,
- 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) )
+ ft_drawing_functions draw )
{
filter_sys_t *p_sys = p_filter->p_sys;
@@ -904,17 +686,19 @@ static inline int RenderAXYZ( filter_t *p_filter,
if (p_region->b_noregionbg) {
/* Render the background just under the text */
- FillPicture( p_picture, STYLE_ALPHA_TRANSPARENT, 0x00, 0x00, 0x00 );
+ draw.fill( p_picture, STYLE_ALPHA_TRANSPARENT, 0x00, 0x00, 0x00,
+ 0, 0, fmt.i_visible_width, fmt.i_visible_height );
} else {
/* Render background under entire subpicture block */
- 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 );
+ draw.extract( p_style->i_background_color, &i_x, &i_y, &i_z );
+ draw.fill( p_picture, p_style->i_background_alpha, i_x, i_y, i_z,
+ 0, 0, fmt.i_visible_width, fmt.i_visible_height );
}
/* Render text's background (from decoder) if any */
RenderBackground(p_region, p_line_head,
p_regionbbox, p_paddedtextbbox, p_textbbox,
- p_picture, ExtractComponents, BlendPixel);
+ p_picture, draw);
/* Render shadow then outline and then normal glyphs */
for( int g = 0; g < 3; g++ )
@@ -929,7 +713,7 @@ static inline int RenderAXYZ( filter_t *p_filter,
RenderCharAXYZ( p_filter, p_picture, p_line,
i_glyph_offset_x, i_glyph_offset_y, g,
- ExtractComponents, BlendPixel );
+ draw );
}
}
@@ -1310,6 +1094,26 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
// p_region_out->i_y = p_region_in->i_y;
// }
+ enum
+ {
+ DRAW_YUVA = 0,
+ DRAW_RGBA,
+ DRAW_ARGB,
+ };
+
+ const ft_drawing_functions drawfuncs[] =
+ {
+ [DRAW_YUVA] = { .extract = YUVFromRGB,
+ .fill = FillYUVAPicture,
+ .blend = BlendGlyphToYUVA },
+ [DRAW_RGBA] = { .extract = RGBFromRGB,
+ .fill = FillRGBAPicture,
+ .blend = BlendGlyphToRGBA },
+ [DRAW_ARGB] = { .extract = RGBFromRGB,
+ .fill = FillARGBPicture,
+ .blend = BlendGlyphToARGB },
+ };
+
for( const vlc_fourcc_t *p_chroma = p_chroma_list; *p_chroma != 0; p_chroma++ )
{
rv = VLC_EGENERIC;
@@ -1321,26 +1125,20 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
®ionbbox, &paddedbbox, &bbox,
VLC_CODEC_YUVA,
&p_region_out->fmt,
- YUVFromRGB,
- FillYUVAPicture,
- BlendYUVAPixel );
+ drawfuncs[DRAW_YUVA] );
else if( *p_chroma == VLC_CODEC_RGBA
|| *p_chroma == VLC_CODEC_BGRA )
rv = RenderAXYZ( p_filter, p_region_out, text_block.p_laid,
®ionbbox, &paddedbbox, &bbox,
*p_chroma,
&p_region_out->fmt,
- RGBFromRGB,
- FillRGBAPicture,
- BlendRGBAPixel );
+ drawfuncs[DRAW_RGBA] );
else if( *p_chroma == VLC_CODEC_ARGB )
rv = RenderAXYZ( p_filter, p_region_out, text_block.p_laid,
®ionbbox, &paddedbbox, &bbox,
VLC_CODEC_ARGB,
&p_region_out->fmt,
- RGBFromRGB,
- FillARGBPicture,
- BlendARGBPixel );
+ drawfuncs[DRAW_ARGB] );
if( !rv )
break;
More information about the vlc-commits
mailing list