Fix code convention, issues with gravity
This commit is contained in:
parent
7aacf26bcb
commit
a3955c6c0a
@ -54,7 +54,6 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
|
||||||
@ -197,23 +196,24 @@ determine_deviation( int width, int height, PangoRectangle rect ) {
|
|||||||
return dw ? dw : dh;
|
return dw ? dw : dh;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static gboolean
|
||||||
search_flist( FontSizeList *flist, int size )
|
search_flist( FontSizeList *flist, int size )
|
||||||
{
|
{
|
||||||
FontSizeList *entry = flist;
|
FontSizeList *entry = flist;
|
||||||
while( entry->next != NULL ) {
|
while( entry->next != NULL ) {
|
||||||
if( entry->size == size )
|
if( entry->size == size )
|
||||||
return true;
|
return TRUE;
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
}
|
}
|
||||||
return false;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FontSizeList *
|
static FontSizeList *
|
||||||
least_deviation_flist( FontSizeList *flist )
|
least_deviation_flist( FontSizeList *flist )
|
||||||
{
|
{
|
||||||
FontSizeList *entry = flist;
|
FontSizeList *entry = flist;
|
||||||
// This works for all practical purposes
|
/* This works for all practical purposes
|
||||||
|
*/
|
||||||
long smallest = 1999999999;
|
long smallest = 1999999999;
|
||||||
FontSizeList *least;
|
FontSizeList *least;
|
||||||
while( entry->next != NULL ) {
|
while( entry->next != NULL ) {
|
||||||
@ -238,7 +238,7 @@ append_to_flist( FontSizeList *flist, FontSizeList *nflist )
|
|||||||
|
|
||||||
static PangoRectangle
|
static PangoRectangle
|
||||||
fit_to_bounds( VipsText *text,
|
fit_to_bounds( VipsText *text,
|
||||||
char *name, int size, PangoRectangle rect, FontSizeList *flist, bool coarse )
|
char *name, int size, PangoRectangle rect, FontSizeList *flist, gboolean coarse )
|
||||||
{
|
{
|
||||||
int buf_size = strlen( name ) + digits_in_num( size ) + 2;
|
int buf_size = strlen( name ) + digits_in_num( size ) + 2;
|
||||||
int deviation;
|
int deviation;
|
||||||
@ -250,8 +250,9 @@ fit_to_bounds( VipsText *text,
|
|||||||
FontSizeList *nflist = (FontSizeList *) malloc( sizeof( FontSizeList ) );
|
FontSizeList *nflist = (FontSizeList *) malloc( sizeof( FontSizeList ) );
|
||||||
|
|
||||||
if( coarse ) {
|
if( coarse ) {
|
||||||
// A factor of X increase in font size causes X^2 increase in the area
|
/* A factor of X increase in font size causes X^2 increase in the area
|
||||||
// occupied by the text
|
* occupied by the text
|
||||||
|
*/
|
||||||
size = (int)((double)size * sqrt( (double)allowed_area / font_area ));
|
size = (int)((double)size * sqrt( (double)allowed_area / font_area ));
|
||||||
} else {
|
} else {
|
||||||
if( allowed_area > font_area ) {
|
if( allowed_area > font_area ) {
|
||||||
@ -276,15 +277,17 @@ fit_to_bounds( VipsText *text,
|
|||||||
nflist->next = NULL;
|
nflist->next = NULL;
|
||||||
append_to_flist( flist, nflist );
|
append_to_flist( flist, nflist );
|
||||||
|
|
||||||
// If we have been through this font size before, find the one with the
|
/* If we have been through this font size before, find the one with the
|
||||||
// smallest deviation and then fit in small adjustments
|
* smallest deviation and then fit in small adjustments
|
||||||
|
*/
|
||||||
if( search_flist( flist, size ) ) {
|
if( search_flist( flist, size ) ) {
|
||||||
if( coarse ) {
|
if( coarse ) {
|
||||||
return fit_to_bounds( text, name, size, rect,
|
return fit_to_bounds( text, name, size, rect,
|
||||||
least_deviation_flist( flist ), false );
|
least_deviation_flist( flist ), FALSE );
|
||||||
} else {
|
} else {
|
||||||
// We cannot do better than this because we will
|
/* We cannot do better than this because we will
|
||||||
// cycle through sizes again
|
* cycle through sizes again
|
||||||
|
*/
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +316,7 @@ vips_text_build( VipsObject *object )
|
|||||||
int deviation = 0;
|
int deviation = 0;
|
||||||
int font_size = 0;
|
int font_size = 0;
|
||||||
char *last;
|
char *last;
|
||||||
bool is_font_size_provided = true;
|
gboolean is_font_size_provided = TRUE;
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_text_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_text_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -325,10 +328,12 @@ vips_text_build( VipsObject *object )
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *font_name[ strlen( text->font ) + 1 ];
|
char *font_name[ strlen( text->font ) + 1 ];
|
||||||
// Extract font size from provided argument
|
/* Extract font size from provided argument
|
||||||
|
*/
|
||||||
last = strrchr( text->font, ' ' );
|
last = strrchr( text->font, ' ' );
|
||||||
|
|
||||||
// Happens for a single word font names
|
/* Happens for a single word font names
|
||||||
|
*/
|
||||||
if( last != '\0' ) {
|
if( last != '\0' ) {
|
||||||
font_size = atol( last );
|
font_size = atol( last );
|
||||||
}
|
}
|
||||||
@ -336,12 +341,13 @@ vips_text_build( VipsObject *object )
|
|||||||
if( font_size ) {
|
if( font_size ) {
|
||||||
strncat( font_name, text->font, last - text->font );
|
strncat( font_name, text->font, last - text->font );
|
||||||
} else {
|
} else {
|
||||||
// Font was more than 1 MAX_word. "Fira Code" would have last
|
/* Font was more than 1 word. "Fira Code" would have last
|
||||||
// pointing to "Code", leading atol to output 0
|
* pointing to "Code", leading atol to output 0
|
||||||
// Fix font_name back to the original in this case
|
* Fix font_name back to the original in this case
|
||||||
|
*/
|
||||||
strcpy( font_name, text->font );
|
strcpy( font_name, text->font );
|
||||||
font_size = text->height;
|
font_size = text->height;
|
||||||
is_font_size_provided = false;
|
is_font_size_provided = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mutex_lock( vips_text_lock );
|
g_mutex_lock( vips_text_lock );
|
||||||
@ -374,10 +380,9 @@ vips_text_build( VipsObject *object )
|
|||||||
flist->area = PANGO_PIXELS( logical_rect.width ) * PANGO_PIXELS( logical_rect.height );
|
flist->area = PANGO_PIXELS( logical_rect.width ) * PANGO_PIXELS( logical_rect.height );
|
||||||
flist->next = NULL;
|
flist->next = NULL;
|
||||||
|
|
||||||
logical_rect = fit_to_bounds( text, font_name, font_size, logical_rect, flist, true );
|
logical_rect = fit_to_bounds( text, font_name, font_size, logical_rect, flist, TRUE );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logical rect does not help us with exact bounds of the text
|
|
||||||
pango_layout_get_extents( text->layout, NULL, &logical_rect );
|
pango_layout_get_extents( text->layout, NULL, &logical_rect );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,19 +400,17 @@ vips_text_build( VipsObject *object )
|
|||||||
width = PANGO_PIXELS( logical_rect.width );
|
width = PANGO_PIXELS( logical_rect.width );
|
||||||
height = PANGO_PIXELS( logical_rect.height );
|
height = PANGO_PIXELS( logical_rect.height );
|
||||||
|
|
||||||
// Match the layout to fit the exact dimensions requested
|
/* Match the layout to fit the exact dimensions requested
|
||||||
// We also apply gravity here
|
* We also apply gravity here
|
||||||
if( !is_font_size_provided && text->width && text->height ) {
|
*/
|
||||||
left = 0;
|
if( text->width && text->height ) {
|
||||||
top = 0;
|
|
||||||
width = PANGO_PIXELS( logical_rect.width );
|
/* Since the layout is bigger than the requested dimensions, we
|
||||||
height = PANGO_PIXELS( logical_rect.height );
|
* scale the layout font description by the same scale
|
||||||
|
* This seems like the only way to resize the layout before it
|
||||||
// Since the layout is bigger than the requested dimensions, we
|
* is rendered. We cannot reliably do resizing after rendering
|
||||||
// scale the layout font description by the same scale
|
* because we lose the lock, and we need to rely on vips_resize
|
||||||
// This seems like the only way to resize the layout before it
|
*/
|
||||||
// is rendered. We cannot reliably do resizing after rendering
|
|
||||||
// because we lose the lock, and we need to rely on vips_resize
|
|
||||||
if( width > text->width || height > text->height ) {
|
if( width > text->width || height > text->height ) {
|
||||||
double scale_w = (double)text->width / width;
|
double scale_w = (double)text->width / width;
|
||||||
double scale_h = (double)text->height / height;
|
double scale_h = (double)text->height / height;
|
||||||
@ -419,54 +422,60 @@ vips_text_build( VipsObject *object )
|
|||||||
pango_layout_set_font_description( text->layout, temp_fd );
|
pango_layout_set_font_description( text->layout, temp_fd );
|
||||||
pango_font_description_free( temp_fd );
|
pango_font_description_free( temp_fd );
|
||||||
|
|
||||||
// Overloading logical_rect as an ink rectangle here to determine the
|
|
||||||
// best gravity
|
|
||||||
// For most cases, gravities with north, south components are completely
|
|
||||||
// useless if we do positioning with logical rect
|
|
||||||
pango_layout_get_extents( text->layout, &logical_rect, NULL );
|
pango_layout_get_extents( text->layout, &logical_rect, NULL );
|
||||||
|
|
||||||
width = PANGO_PIXELS( logical_rect.width );
|
width = PANGO_PIXELS( logical_rect.width );
|
||||||
height = PANGO_PIXELS( logical_rect.height );
|
height = PANGO_PIXELS( logical_rect.height );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int padl = 0;
|
||||||
|
int padt = 0;
|
||||||
|
|
||||||
switch( text->gravity ) {
|
switch( text->gravity ) {
|
||||||
case VIPS_GRAVITY_CENTER:
|
case VIPS_GRAVITY_CENTER:
|
||||||
left = ( text->width - width ) / 2;
|
padl = ( text->width - width ) / 2;
|
||||||
|
padt = ( text->height - height ) / 2;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_NORTH:
|
case VIPS_GRAVITY_NORTH:
|
||||||
top = ( height - text->height ) / 2;
|
padl = ( text->width - width ) / 2;
|
||||||
left = ( text->width - width ) / 2;
|
padt = 0;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_EAST:
|
case VIPS_GRAVITY_EAST:
|
||||||
left = text->width - width;
|
padl = text->width - width;
|
||||||
|
padt = ( text->height - height ) / 2;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_SOUTH:
|
case VIPS_GRAVITY_SOUTH:
|
||||||
top = ( text->height - height ) / 2;
|
padl = ( text->width - width ) / 2;
|
||||||
left = ( text->width - width ) / 2;
|
padt = text->height - height;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_WEST:
|
case VIPS_GRAVITY_WEST:
|
||||||
|
padl = 0;
|
||||||
|
padt = ( text->height - height ) / 2;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_NORTH_EAST:
|
case VIPS_GRAVITY_NORTH_EAST:
|
||||||
top = ( height - text->height ) / 2;
|
padl = text->width - width;
|
||||||
left = text->width - width;
|
padt = 0;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_SOUTH_EAST:
|
case VIPS_GRAVITY_SOUTH_EAST:
|
||||||
top = ( text->height - height ) / 2;
|
padl = text->width - width;
|
||||||
left = text->width - width;
|
padt = text->height - height;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_SOUTH_WEST:
|
case VIPS_GRAVITY_SOUTH_WEST:
|
||||||
top = ( text->height - height ) / 2;
|
padl = 0;
|
||||||
|
padt = text->height - height;
|
||||||
break;
|
break;
|
||||||
case VIPS_GRAVITY_NORTH_WEST:
|
case VIPS_GRAVITY_NORTH_WEST:
|
||||||
top = ( height - text->height ) / 2;
|
padl = 0;
|
||||||
|
padt = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
left = -1 * left;
|
|
||||||
top = -1 * top;
|
left = left - ( width > text->width ? 0 : padl ) + PANGO_PIXELS( logical_rect.x );
|
||||||
width = text->width;
|
top = top - ( height > text->height ? 0 : padt ) + PANGO_PIXELS( logical_rect.y );
|
||||||
height = text->height;
|
width = text->width > width ? text->width : width;
|
||||||
|
height = text->height > height ? text->height : height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can happen for "", for example.
|
/* Can happen for "", for example.
|
||||||
|
@ -47,7 +47,8 @@ typedef enum {
|
|||||||
VIPS_GRAVITY_NORTH_EAST,
|
VIPS_GRAVITY_NORTH_EAST,
|
||||||
VIPS_GRAVITY_SOUTH_EAST,
|
VIPS_GRAVITY_SOUTH_EAST,
|
||||||
VIPS_GRAVITY_SOUTH_WEST,
|
VIPS_GRAVITY_SOUTH_WEST,
|
||||||
VIPS_GRAVITY_NORTH_WEST
|
VIPS_GRAVITY_NORTH_WEST,
|
||||||
|
VIPS_GRAVITY_LAST
|
||||||
} VipsGravity;
|
} VipsGravity;
|
||||||
|
|
||||||
int vips_black( VipsImage **out, int width, int height, ... )
|
int vips_black( VipsImage **out, int width, int height, ... )
|
||||||
|
@ -63,6 +63,7 @@ vips_gravity_get_type( void )
|
|||||||
{VIPS_GRAVITY_SOUTH_EAST, "VIPS_GRAVITY_SOUTH_EAST", "south-east"},
|
{VIPS_GRAVITY_SOUTH_EAST, "VIPS_GRAVITY_SOUTH_EAST", "south-east"},
|
||||||
{VIPS_GRAVITY_SOUTH_WEST, "VIPS_GRAVITY_SOUTH_WEST", "south-west"},
|
{VIPS_GRAVITY_SOUTH_WEST, "VIPS_GRAVITY_SOUTH_WEST", "south-west"},
|
||||||
{VIPS_GRAVITY_NORTH_WEST, "VIPS_GRAVITY_NORTH_WEST", "north-west"},
|
{VIPS_GRAVITY_NORTH_WEST, "VIPS_GRAVITY_NORTH_WEST", "north-west"},
|
||||||
|
{VIPS_GRAVITY_LAST, "VIPS_GRAVITY_LAST", "last"},
|
||||||
{0, NULL, NULL}
|
{0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user