diff --git a/ChangeLog b/ChangeLog index 00535368..866ab4d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,11 @@ - implement shrink-on-load for tiff pyramids [jcupitt] - added vips_image_set_blob_copy() [jcupitt] +21/11/18 started 8.7.2 +- more info output for temp files to help diagnose problems +- vips_text() could set the wrong DPI +- vips_text() leaked in autofit mode + 23/9/18 started 8.7.1 - update function list in docs [janko-m] - test for g_str_to_ascii() [jcupitt] diff --git a/libvips/create/text.c b/libvips/create/text.c index c0b14694..a6a4810a 100644 --- a/libvips/create/text.c +++ b/libvips/create/text.c @@ -22,6 +22,9 @@ * - better fitting of fonts with overhanging edges, thanks AdriĆ  * 26/4/18 fangqiao * - add fontfile option + * 5/12/18 + * - fitting mode could set wrong dpi + * - fitting mode leaked */ /* @@ -170,8 +173,6 @@ vips_text_get_extents( VipsText *text, VipsRect *extents ) pango_ft2_font_map_set_resolution( PANGO_FT2_FONT_MAP( vips_text_fontmap ), text->dpi, text->dpi ); - text->context = pango_font_map_create_context( - PANGO_FONT_MAP( vips_text_fontmap ) ); if( !(text->layout = text_layout_new( text->context, text->text, text->font, @@ -180,17 +181,18 @@ vips_text_get_extents( VipsText *text, VipsRect *extents ) pango_layout_get_pixel_extents( text->layout, &ink_rect, &logical_rect ); - extents->left = ink_rect.x; extents->top = ink_rect.y; extents->width = ink_rect.width; extents->height = ink_rect.height; #ifdef DEBUG - printf( "vips_text_get_extents: dpi = %d, " - "left = %d, top = %d, width = %d, height = %d\n", - text->dpi, - extents->left, extents->top, extents->width, extents->height ); + printf( "vips_text_get_extents: dpi = %d\n", text->dpi ); + printf( " ink left = %d, top = %d, width = %d, height = %d\n", + ink_rect.x, ink_rect.y, ink_rect.width, ink_rect.height ); + printf( " logical left = %d, top = %d, width = %d, height = %d\n", + logical_rect.x, logical_rect.y, + logical_rect.width, logical_rect.height ); #endif /*DEBUG*/ return( 0 ); @@ -215,27 +217,32 @@ vips_text_rect_difference( VipsRect *target, VipsRect *extents ) /* Adjust text->dpi to try to fit to the bounding box. */ static int -vips_text_autofit( VipsText *text, VipsRect *out_extents ) +vips_text_autofit( VipsText *text ) { VipsRect target; VipsRect extents; - VipsRect previous_extents; int difference; int previous_difference; int previous_dpi; int lower_dpi; int upper_dpi; - VipsRect lower_extents; - VipsRect upper_extents; /* First, repeatedly double or halve dpi until we pass the correct * value. This will give us a lower and upper bound. */ + target.left = 0; + target.top = 0; target.width = text->width; target.height = text->height; previous_dpi = -1; +#ifdef DEBUG + printf( "vips_text_autofit: " + "target left = %d, top = %d, width = %d, height = %d\n", + target.left, target.top, target.width, target.height ); +#endif /*DEBUG*/ + for(;;) { if( vips_text_get_extents( text, &extents ) ) return( -1 ); @@ -246,7 +253,6 @@ vips_text_autofit( VipsText *text, VipsRect *out_extents ) if( previous_dpi == -1 ) { previous_dpi = text->dpi; previous_difference = difference; - previous_extents = extents; } /* Hit the size, or we straddle the target. @@ -256,7 +262,6 @@ vips_text_autofit( VipsText *text, VipsRect *out_extents ) break; previous_difference = difference; - previous_extents = extents; previous_dpi = text->dpi; text->dpi = difference < 0 ? text->dpi * 2 : text->dpi / 2; @@ -266,17 +271,18 @@ vips_text_autofit( VipsText *text, VipsRect *out_extents ) /* We've been coming down. */ lower_dpi = text->dpi; - lower_extents = extents; upper_dpi = previous_dpi; - upper_extents = previous_extents; } else { lower_dpi = previous_dpi; - lower_extents = previous_extents; upper_dpi = text->dpi; - upper_extents = extents; } +#ifdef DEBUG + printf( "vips_text_autofit: lower dpi = %d, upper dpi = %d\n", + lower_dpi, upper_dpi ); +#endif /*DEBUG*/ + /* Refine lower and upper until they are almost touching. */ while( upper_dpi - lower_dpi > 1 && @@ -288,31 +294,26 @@ vips_text_autofit( VipsText *text, VipsRect *out_extents ) target.top = extents.top; difference = vips_text_rect_difference( &target, &extents ); - if( difference < 0 ) { + if( difference < 0 ) lower_dpi = text->dpi; - lower_extents = extents; - } - else { + else upper_dpi = text->dpi; - upper_extents = extents; - } } /* If we've hit the target exactly and quit the loop, diff will be 0 * and we can use upper. Otherwise we are straddling the target and we * must take lower. */ - if( difference == 0 ) { + if( difference == 0 ) text->dpi = upper_dpi; - *out_extents = upper_extents; - } - else { + else text->dpi = lower_dpi; - *out_extents = lower_extents; - } - g_object_set( text, "autofit_dpi", text->dpi, NULL ); +#ifdef DEBUG + printf( "vips_text_autofit: final dpi = %d\n", text->dpi ); +#endif /*DEBUG*/ + return( 0 ); } @@ -340,6 +341,9 @@ vips_text_build( VipsObject *object ) if( !vips_text_fontmap ) vips_text_fontmap = pango_ft2_font_map_new(); + text->context = pango_font_map_create_context( + PANGO_FONT_MAP( vips_text_fontmap ) ); + if( text->fontfile && !FcConfigAppFontAddFile( NULL, (const FcChar8 *) text->fontfile ) ) { @@ -354,15 +358,14 @@ vips_text_build( VipsObject *object ) */ if( vips_object_argument_isset( object, "height" ) && !vips_object_argument_isset( object, "dpi" ) ) { - if( vips_text_autofit( text, &extents ) ) + if( vips_text_autofit( text ) ) return( -1 ); } - else - if( vips_text_get_extents( text, &extents ) ) - return( -1 ); - /* Can happen for "", for example. + /* Layout. Can fail for "", for example. */ + if( vips_text_get_extents( text, &extents ) ) + return( -1 ); if( extents.width == 0 || extents.height == 0 ) { vips_error( class->nickname, "%s", _( "no text to render" ) ); diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index e7d71378..cfb42471 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -188,6 +188,11 @@ vips__open_image_write( const char *filename, gboolean temp ) fd = -1; +#ifndef O_TMPFILE + if( temp ) + g_info( "vips__open_image_write: O_TMPFILE not available" ); +#endif /*!O_TMPFILE*/ + #ifdef O_TMPFILE /* Linux-only extension creates an unlinked file. CREAT and TRUNC must * be clear. The filename arg to open() must name a directory. @@ -199,9 +204,13 @@ vips__open_image_write( const char *filename, gboolean temp ) if( temp ) { char *dirname; + g_info( "vips__open_image_write: opening with O_TMPFILE" ); dirname = g_path_get_dirname( filename ); fd = vips_tracked_open( dirname, O_TMPFILE | O_RDWR , 0666 ); g_free( dirname ); + + if( fd < 0 ) + g_info( "vips__open_image_write: O_TMPFILE failed!" ); } #endif /*O_TMPFILE*/ @@ -211,14 +220,19 @@ vips__open_image_write( const char *filename, gboolean temp ) /* On Windows, setting _O_TEMPORARY will delete the file automatically * on process exit, even if the processes crashes. */ - if( temp ) + if( temp ) { + g_info( "vips__open_image_write: setting _O_TEMPORARY" ); flags |= _O_TEMPORARY; + } #endif /*_O_TEMPORARY*/ - if( fd < 0 ) + if( fd < 0 ) { + g_info( "vips__open_image_write: simple open" ); fd = vips_tracked_open( filename, flags, 0666 ); + } if( fd < 0 ) { + g_info( "vips__open_image_write: failed!" ); vips_error_system( errno, "VipsImage", _( "unable to write to \"%s\"" ), filename ); return( -1 );