text: use MT-safe pango_cairo_font_map_get_default (#2848)

* text: use MT-safe `pango_cairo_font_map_get_default`

* Increase minimum Pango version to v1.32.6 (released Jan 2013)
This commit is contained in:
Kleis Auke Wolthuizen 2022-06-08 17:06:45 +02:00 committed by GitHub
parent b086b3f61a
commit 45a99238e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 35 deletions

View File

@ -1221,7 +1221,7 @@ AC_ARG_WITH([pangocairo],
[build without pangocairo (default: test)])) [build without pangocairo (default: test)]))
if test x"$with_pangocairo" != x"no"; then if test x"$with_pangocairo" != x"no"; then
PKG_CHECK_MODULES(PANGOCAIRO, pangocairo, PKG_CHECK_MODULES(PANGOCAIRO, pangocairo >= 1.32.6,
[AC_DEFINE(HAVE_PANGOCAIRO,1,[define if you have pangocairo installed.]) [AC_DEFINE(HAVE_PANGOCAIRO,1,[define if you have pangocairo installed.])
with_pangocairo=yes with_pangocairo=yes
PACKAGES_USED="$PACKAGES_USED pangocairo" PACKAGES_USED="$PACKAGES_USED pangocairo"
@ -1241,7 +1241,7 @@ AC_ARG_WITH([fontconfig],
[build without fontconfig (default: test)])) [build without fontconfig (default: test)]))
if test x"$with_pangocairo" != x"no" -a x"$with_fontconfig" != x"no"; then if test x"$with_pangocairo" != x"no" -a x"$with_fontconfig" != x"no"; then
PKG_CHECK_MODULES(FONTCONFIG, fontconfig pangoft2 >= 1.4, PKG_CHECK_MODULES(FONTCONFIG, fontconfig pangoft2 >= 1.32.6,
[AC_DEFINE(HAVE_FONTCONFIG,1,[define if you have fontconfig installed.]) [AC_DEFINE(HAVE_FONTCONFIG,1,[define if you have fontconfig installed.])
with_fontconfig=yes with_fontconfig=yes
PACKAGES_USED="$PACKAGES_USED fontconfig pangoft2" PACKAGES_USED="$PACKAGES_USED fontconfig pangoft2"

View File

@ -106,6 +106,7 @@ typedef struct _VipsText {
char *fontfile; char *fontfile;
gboolean rgba; gboolean rgba;
PangoFontMap *fontmap;
PangoContext *context; PangoContext *context;
PangoLayout *layout; PangoLayout *layout;
@ -115,18 +116,10 @@ typedef VipsCreateClass VipsTextClass;
G_DEFINE_TYPE( VipsText, vips_text, VIPS_TYPE_CREATE ); G_DEFINE_TYPE( VipsText, vips_text, VIPS_TYPE_CREATE );
/* ... single-thread the body of vips_text() with this. /* ... single-thread vips_text_fontfiles with this.
*/ */
static GMutex *vips_text_lock = NULL; static GMutex *vips_text_lock = NULL;
/* Just have one of these and reuse it.
*
* This does not unref cleanly on many platforms, so we will leak horribly
* unless we reuse it. Sadly this means vips_text() needs to use a lock
* internally to single-thread text rendering.
*/
static PangoFontMap *vips_text_fontmap = NULL;
/* All the fontfiles we've loaded. fontconfig lets you add a fontfile /* All the fontfiles we've loaded. fontconfig lets you add a fontfile
* repeatedly, and we obviously don't want that. * repeatedly, and we obviously don't want that.
*/ */
@ -196,7 +189,7 @@ vips_text_get_extents( VipsText *text, VipsRect *extents )
PangoRectangle logical_rect; PangoRectangle logical_rect;
pango_cairo_font_map_set_resolution( pango_cairo_font_map_set_resolution(
PANGO_CAIRO_FONT_MAP( vips_text_fontmap ), text->dpi ); PANGO_CAIRO_FONT_MAP( text->fontmap ), text->dpi );
VIPS_UNREF( text->layout ); VIPS_UNREF( text->layout );
if( !(text->layout = text_layout_new( text->context, if( !(text->layout = text_layout_new( text->context,
@ -365,18 +358,16 @@ vips_text_build( VipsObject *object )
return( -1 ); return( -1 );
} }
g_mutex_lock( vips_text_lock ); text->fontmap = pango_cairo_font_map_get_default();
text->context = pango_font_map_create_context(
PANGO_FONT_MAP( text->fontmap ) );
if( !vips_text_fontmap ) g_mutex_lock( vips_text_lock );
vips_text_fontmap = pango_cairo_font_map_new();
if( !vips_text_fontfiles ) if( !vips_text_fontfiles )
vips_text_fontfiles = vips_text_fontfiles =
g_hash_table_new( g_str_hash, g_str_equal ); g_hash_table_new( g_str_hash, g_str_equal );
text->context = pango_font_map_create_context(
PANGO_FONT_MAP( vips_text_fontmap ) );
#ifdef HAVE_FONTCONFIG #ifdef HAVE_FONTCONFIG
if( text->fontfile && if( text->fontfile &&
!g_hash_table_lookup( vips_text_fontfiles, text->fontfile ) ) { !g_hash_table_lookup( vips_text_fontfiles, text->fontfile ) ) {
@ -394,9 +385,9 @@ vips_text_build( VipsObject *object )
/* We need to inform that pango should invalidate its /* We need to inform that pango should invalidate its
* fontconfig cache whenever any changes are made. * fontconfig cache whenever any changes are made.
*/ */
if( PANGO_IS_FC_FONT_MAP( vips_text_fontmap ) ) if( PANGO_IS_FC_FONT_MAP( text->fontmap ) )
pango_fc_font_map_cache_clear( pango_fc_font_map_cache_clear(
PANGO_FC_FONT_MAP( vips_text_fontmap ) ); PANGO_FC_FONT_MAP( text->fontmap ) );
} }
#else /*!HAVE_FONTCONFIG*/ #else /*!HAVE_FONTCONFIG*/
if( text->fontfile ) if( text->fontfile )
@ -404,27 +395,25 @@ vips_text_build( VipsObject *object )
_( "ignoring fontfile (no fontconfig support)" ) ); _( "ignoring fontfile (no fontconfig support)" ) );
#endif /*HAVE_FONTCONFIG*/ #endif /*HAVE_FONTCONFIG*/
g_mutex_unlock( vips_text_lock );
/* If our caller set height and not dpi, we adjust dpi until /* If our caller set height and not dpi, we adjust dpi until
* we get a fit. * we get a fit.
*/ */
if( vips_object_argument_isset( object, "height" ) && if( vips_object_argument_isset( object, "height" ) &&
!vips_object_argument_isset( object, "dpi" ) ) { !vips_object_argument_isset( object, "dpi" ) ) {
if( vips_text_autofit( text ) ) { if( vips_text_autofit( text ) )
g_mutex_unlock( vips_text_lock );
return( -1 ); return( -1 );
} }
}
/* Layout. Can fail for "", for example. /* Layout. Can fail for "", for example.
*/ */
if( vips_text_get_extents( text, &extents ) ) { if( vips_text_get_extents( text, &extents ) )
g_mutex_unlock( vips_text_lock );
return( -1 ); return( -1 );
}
if( extents.width == 0 || if( extents.width == 0 ||
extents.height == 0 ) { extents.height == 0 ) {
vips_error( class->nickname, "%s", _( "no text to render" ) ); vips_error( class->nickname, "%s", _( "no text to render" ) );
g_mutex_unlock( vips_text_lock );
return( -1 ); return( -1 );
} }
@ -434,7 +423,6 @@ vips_text_build( VipsObject *object )
extents.height >= 32768 ) { extents.height >= 32768 ) {
vips_error( class->nickname, vips_error( class->nickname,
"%s", _( "text image too large" ) ); "%s", _( "text image too large" ) );
g_mutex_unlock( vips_text_lock );
return( -1 ); return( -1 );
} }
@ -448,10 +436,8 @@ vips_text_build( VipsObject *object )
image->Yoffset = extents.top; image->Yoffset = extents.top;
if( vips_image_pipelinev( image, VIPS_DEMAND_STYLE_ANY, NULL ) || if( vips_image_pipelinev( image, VIPS_DEMAND_STYLE_ANY, NULL ) ||
vips_image_write_prepare( image ) ) { vips_image_write_prepare( image ) )
g_mutex_unlock( vips_text_lock );
return( -1 ); return( -1 );
}
surface = cairo_image_surface_create_for_data( surface = cairo_image_surface_create_for_data(
VIPS_IMAGE_ADDR( image, 0, 0 ), VIPS_IMAGE_ADDR( image, 0, 0 ),
@ -467,8 +453,6 @@ vips_text_build( VipsObject *object )
cairo_destroy( cr ); cairo_destroy( cr );
g_mutex_unlock( vips_text_lock );
if( text->rgba ) { if( text->rgba ) {
int y; int y;

View File

@ -329,7 +329,7 @@ if libwebp_dep.found()
cfg_var.set('HAVE_LIBWEBP', '1') cfg_var.set('HAVE_LIBWEBP', '1')
endif endif
pangocairo_dep = dependency('pangocairo', required: get_option('pangocairo')) pangocairo_dep = dependency('pangocairo', version: '>=1.32.6', required: get_option('pangocairo'))
if pangocairo_dep.found() if pangocairo_dep.found()
libvips_deps += pangocairo_dep libvips_deps += pangocairo_dep
cfg_var.set('HAVE_PANGOCAIRO', '1') cfg_var.set('HAVE_PANGOCAIRO', '1')
@ -338,7 +338,7 @@ endif
fontconfig_dep = dependency('fontconfig', required: get_option('fontconfig')) fontconfig_dep = dependency('fontconfig', required: get_option('fontconfig'))
if fontconfig_dep.found() and pangocairo_dep.found() if fontconfig_dep.found() and pangocairo_dep.found()
libvips_deps += fontconfig_dep libvips_deps += fontconfig_dep
libvips_deps += dependency('pangoft2', version: '>=1.4') libvips_deps += dependency('pangoft2', version: '>=1.32.6')
cfg_var.set('HAVE_FONTCONFIG', '1') cfg_var.set('HAVE_FONTCONFIG', '1')
endif endif