John Cupitt 2022-11-10 15:46:46 +00:00 committed by GitHub
parent 144834a6aa
commit ef2646ef6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 13 deletions

View File

@ -18,6 +18,7 @@ master
- threadpools size dynamically with load
- operations can hint threadpool size
- support for N-colour ICC profiles
- add @wrap to vips_text()
- GIF load supports truncated frames [tlsa]
9/11/22 started 8.13.4

View File

@ -63,6 +63,20 @@
* The im_benchmark() operations are for testing the VIPS SMP system.
*/
/**
* VipsTextWrap:
* @VIPS_TEXT_WRAP_WORD: wrap at word boundaries
* @VIPS_TEXT_WRAP_CHAR: wrap at character boundaries
* @VIPS_TEXT_WRAP_WORD_CHAR: wrap at word boundaries, but fall back to
* character boundaries if there is not enough space for a full word
* @VIPS_TEXT_WRAP_NONE: no wrapping
*
* Sets the word wrapping style for vips_text() when used with a maximum
* width.
*
* See also: vips_text().
*/
G_DEFINE_ABSTRACT_TYPE( VipsCreate, vips_create, VIPS_TYPE_OPERATION );
static int

View File

@ -35,6 +35,8 @@
* 12/4/21
* - switch to cairo for text rendering
* - add rgba flag
* 31/10/22
* - add @wrap
*/
/*
@ -105,6 +107,7 @@ typedef struct _VipsText {
int dpi;
char *fontfile;
gboolean rgba;
VipsTextWrap wrap;
PangoFontMap *fontmap;
PangoContext *context;
@ -139,11 +142,13 @@ vips_text_dispose( GObject *gobject )
static PangoLayout *
text_layout_new( PangoContext *context,
const char *text, const char *font, int width, int spacing,
VipsAlign align, gboolean justify )
VipsAlign align, VipsTextWrap wrap, gboolean justify )
{
PangoLayout *layout;
PangoFontDescription *font_description;
PangoAlignment palign;
PangoWrapMode pwrap;
int pwidth;
layout = pango_layout_new( context );
pango_layout_set_markup( layout, text, -1 );
@ -151,9 +156,7 @@ text_layout_new( PangoContext *context,
font_description = pango_font_description_from_string( font );
pango_layout_set_font_description( layout, font_description );
pango_font_description_free( font_description );
if( width > 0 )
pango_layout_set_width( layout, width * PANGO_SCALE );
pango_layout_set_justify( layout, justify );
if( spacing > 0 )
pango_layout_set_spacing( layout, spacing * PANGO_SCALE );
@ -177,7 +180,33 @@ text_layout_new( PangoContext *context,
}
pango_layout_set_alignment( layout, palign );
pango_layout_set_justify( layout, justify );
switch( wrap ) {
case VIPS_TEXT_WRAP_NONE:
pwrap = PANGO_WRAP_WORD_CHAR;
pwidth = -1;
break;
case VIPS_TEXT_WRAP_CHAR:
pwrap = PANGO_WRAP_CHAR;
pwidth = width * PANGO_SCALE;
break;
case VIPS_TEXT_WRAP_WORD:
pwrap = PANGO_WRAP_WORD;
pwidth = width * PANGO_SCALE;
break;
case VIPS_TEXT_WRAP_WORD_CHAR:
default:
pwrap = PANGO_WRAP_WORD_CHAR;
pwidth = width * PANGO_SCALE;
break;
}
pango_layout_set_wrap( layout, pwrap );
if( pwidth > 0 )
pango_layout_set_width( layout, width * PANGO_SCALE );
return( layout );
}
@ -194,7 +223,8 @@ vips_text_get_extents( VipsText *text, VipsRect *extents )
VIPS_UNREF( text->layout );
if( !(text->layout = text_layout_new( text->context,
text->text, text->font,
text->width, text->spacing, text->align, text->justify )) )
text->width, text->spacing, text->align, text->wrap,
text->justify )) )
return( -1 );
pango_layout_get_pixel_extents( text->layout,
@ -552,41 +582,48 @@ vips_text_class_init( VipsTextClass *class )
G_STRUCT_OFFSET( VipsText, justify ),
FALSE );
VIPS_ARG_INT( class, "dpi", 9,
VIPS_ARG_INT( class, "dpi", 10,
_( "DPI" ),
_( "DPI to render at" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsText, dpi ),
1, 1000000, 72 );
VIPS_ARG_INT( class, "autofit_dpi", 10,
VIPS_ARG_INT( class, "autofit_dpi", 11,
_( "Autofit DPI" ),
_( "DPI selected by autofit" ),
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
G_STRUCT_OFFSET( VipsText, dpi ),
1, 1000000, 72 );
VIPS_ARG_INT( class, "spacing", 11,
VIPS_ARG_INT( class, "spacing", 12,
_( "Spacing" ),
_( "Line spacing" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsText, spacing ),
0, 1000000, 0 );
VIPS_ARG_STRING( class, "fontfile", 12,
VIPS_ARG_STRING( class, "fontfile", 13,
_( "Font file" ),
_( "Load this font file" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsText, fontfile ),
NULL );
VIPS_ARG_BOOL( class, "rgba", 9,
VIPS_ARG_BOOL( class, "rgba", 14,
_( "RGBA" ),
_( "Enable RGBA output" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsText, rgba ),
FALSE );
VIPS_ARG_ENUM( class, "wrap", 15,
_( "Wrap" ),
_( "Wrap lines on word or character boundaries" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsText, wrap ),
VIPS_TYPE_TEXT_WRAP, VIPS_TEXT_WRAP_WORD );
}
static void
@ -594,6 +631,7 @@ vips_text_init( VipsText *text )
{
text->align = VIPS_ALIGN_LOW;
text->dpi = 72;
text->wrap = VIPS_TEXT_WRAP_WORD;
VIPS_SETSTR( text->font, "sans 12" );
}
@ -617,6 +655,7 @@ vips_text_init( VipsText *text )
* * @autofit_dpi: %gint, read out auto-fitted DPI
* * @rgba: %gboolean, enable RGBA output
* * @spacing: %gint, space lines by this in points
* * @wrap: #VipsTextWrap, wrap lines on characters or words
*
* Draw the string @text to an image. @out is normally a one-band 8-bit
* unsigned char image, with 0 for no text and 255 for text. Values between
@ -635,8 +674,10 @@ vips_text_init( VipsText *text )
* You can specify a font to load with @fontfile. You'll need to also set the
* name of the font with @font.
*
* @width is the number of pixels to word-wrap at. Lines of text wider than
* this will be broken at word boundaries.
* @width is the number of pixels to word-wrap at. By default, lines of text
* wider than this will be broken at word boundaries.
* Use @wrap to set lines to wrap on word or character boundaries, or to
* disable line breaks.
*
* Set @justify to turn on line justification.
* @align can be used to set the alignment style for multi-line

View File

@ -38,6 +38,14 @@
extern "C" {
#endif /*__cplusplus*/
typedef enum {
VIPS_TEXT_WRAP_WORD = 0,
VIPS_TEXT_WRAP_CHAR,
VIPS_TEXT_WRAP_WORD_CHAR,
VIPS_TEXT_WRAP_NONE,
VIPS_TEXT_WRAP_LAST
} VipsTextWrap;
VIPS_API
int vips_black( VipsImage **out, int width, int height, ... )
G_GNUC_NULL_TERMINATED;

View File

@ -417,6 +417,11 @@ class TestCreate:
# text rendering systems
assert abs(im.width - 500) < 50
# test wrap
im1 = pyvips.Image.text("helloworld", width=100, dpi=500)
im2 = pyvips.Image.text("helloworld", width=100, dpi=500, wrap="char")
assert im1.width > im2.width
def test_tonelut(self):
im = pyvips.Image.tonelut()
assert im.bands == 1