Fix code convention, issues with gravity

This commit is contained in:
gargsms 2017-09-18 18:34:50 +05:30
parent 7aacf26bcb
commit a3955c6c0a
3 changed files with 67 additions and 56 deletions

View File

@ -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.

View File

@ -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, ... )

View File

@ -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}
}; };