@ -27,9 +27,11 @@
# include "batch.hh"
# include "face-options.hh"
# include "glib.h"
# include "main-font-text.hh"
# include "output-options.hh"
# include <cmath>
# include <hb-subset.h>
static hb_face_t * preprocess_face ( hb_face_t * face )
@ -674,6 +676,93 @@ parse_drop_tables (const char *name,
}
# ifndef HB_NO_VAR
// Parses an axis position string and sets min, default, and max to
// the requested values. If a value should be set to it's default value
// then it will be set to NaN.
static gboolean
parse_axis_position ( const char * s ,
float * min ,
float * def ,
float * max ,
gboolean * drop ,
GError * * error )
{
const char * part = strpbrk ( s , " : " ) ;
* drop = false ;
if ( ! part ) {
// Single value.
if ( strcmp ( s , " drop " ) = = 0 )
{
* min = NAN ;
* def = NAN ;
* max = NAN ;
* drop = true ;
return true ;
}
errno = 0 ;
char * p ;
float axis_value = strtof ( s , & p ) ;
if ( errno | | s = = p )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
return false ;
}
* min = axis_value ;
* def = axis_value ;
* max = axis_value ;
return true ;
}
float values [ 3 ] ;
int count = 0 ;
for ( int i = 0 ; i < 3 ; i + + ) {
errno = 0 ;
count + + ;
if ( ! * s | | part = = s ) {
values [ i ] = NAN ;
if ( part = = nullptr ) break ;
s = part + 1 ;
part = strpbrk ( s , " : " ) ;
continue ;
}
char * pend ;
values [ i ] = strtof ( s , & pend ) ;
if ( errno | | s = = pend | | ( part & & pend ! = part ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
return false ;
}
if ( part = = nullptr ) break ;
s = pend + 1 ;
part = strpbrk ( s , " : " ) ;
}
if ( count = = 2 ) {
* min = values [ 0 ] ;
* def = NAN ;
* max = values [ 1 ] ;
return true ;
} else if ( count = = 3 ) {
* min = values [ 0 ] ;
* def = values [ 1 ] ;
* max = values [ 2 ] ;
return true ;
}
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
return false ;
}
static gboolean
parse_instance ( const char * name ,
const char * arg ,
@ -686,9 +775,10 @@ parse_instance (const char *name,
return true ;
}
char * s = strtok ( ( char * ) arg , " = " ) ;
while ( s )
char * s ;
while ( ( s = strtok ( ( char * ) arg , " = " ) ) )
{
arg = nullptr ;
unsigned len = strlen ( s ) ;
if ( len > 4 ) //Axis tags are 4 bytes.
{
@ -707,89 +797,51 @@ parse_instance (const char *name,
return false ;
}
# ifdef HB_EXPERIMENTAL_API
char * pp = s ;
pp = strpbrk ( pp , " : " ) ;
if ( pp ) // partial instancing
gboolean drop ;
float min , def , max ;
if ( ! parse_axis_position ( s , & min , & def , & max , & drop , error ) )
return false ;
if ( drop )
{
errno = 0 ;
char * pend ;
float min_val = strtof ( s , & pend ) ;
if ( errno | | s = = pend | | pend ! = pp )
if ( ! hb_subset_input_pin_axis_to_default ( subset_main - > input ,
subset_main - > face ,
axis_tag ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
" Cannot pin axis: '%c%c%c%c', not present in fvar " , HB_UNTAG ( axis_tag ) ) ;
return false ;
}
pp + + ;
float max_val = strtof ( pp , & pend ) ;
/* we need to specify 2 values or 3 values for partial instancing:
* at least new min and max values , new default is optional */
if ( errno | | pp = = pend | | ( * pend ! = ' : ' & & * pend ! = ' \0 ' ) )
continue ;
}
if ( min = = def & & def = = max ) {
if ( ! hb_subset_input_pin_axis_location ( subset_main - > input ,
subset_main - > face , axis_tag ,
def ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
" Cannot pin axis: '%c%c%c%c', not present in fvar " , HB_UNTAG ( axis_tag ) ) ;
return false ;
}
/* 3 values are specified */
float * def_val_p = nullptr ;
float def_val ;
if ( * pend = = ' : ' )
{
def_val = max_val ;
def_val_p = & def_val ;
pp = pend + 1 ;
max_val = strtof ( pp , & pend ) ;
if ( errno | | pp = = pend | | * pend ! = ' \0 ' )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
return false ;
}
}
if ( ! hb_subset_input_set_axis_range ( subset_main - > input , subset_main - > face , axis_tag , min_val , max_val , def_val_p ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Error: axis: '%c%c%c%c', not present in fvar or invalid range with min:%.6f max:%.6f " ,
HB_UNTAG ( axis_tag ) , ( double ) min_val , ( double ) max_val ) ;
return false ;
}
continue ;
}
else
{
# endif
if ( strcmp ( s , " drop " ) = = 0 )
{
if ( ! hb_subset_input_pin_axis_to_default ( subset_main - > input , subset_main - > face , axis_tag ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Cannot pin axis: '%c%c%c%c', not present in fvar " , HB_UNTAG ( axis_tag ) ) ;
return false ;
}
}
else
{
errno = 0 ;
char * p ;
float axis_value = strtof ( s , & p ) ;
if ( errno | | s = = p )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Failed parsing axis value at: '%s' " , s ) ;
return false ;
}
if ( ! hb_subset_input_pin_axis_location ( subset_main - > input , subset_main - > face , axis_tag , axis_value ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Cannot pin axis: '%c%c%c%c', not present in fvar " , HB_UNTAG ( axis_tag ) ) ;
return false ;
}
}
# ifdef HB_EXPERIMENTAL_API
if ( ! hb_subset_input_set_axis_range ( subset_main - > input ,
subset_main - > face , axis_tag ,
min , max , def ) )
{
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Cannot pin axis: '%c%c%c%c', not present in fvar " , HB_UNTAG ( axis_tag ) ) ;
return false ;
}
continue ;
# endif
s = strtok ( nullptr , " = " ) ;
g_set_error ( error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
" Partial instancing is not supported. " ) ;
return false ;
}
return true ;
@ -1028,7 +1080,7 @@ subset_main_t::add_options ()
{ " variations " , 0 , 0 , G_OPTION_ARG_CALLBACK , ( gpointer ) & parse_instance ,
" (Partially|Fully) Instantiate a variable font. A location consists of the tag "
" of a variation axis, followed by '=', followed by a number or the literal "
" string 'drop'. For example: --variations= \" wdth=100 wght=200 \" or --instance = \" wdth=drop \" "
" string 'drop'. For example: --variations= \" wdth=100 wght=200 \" or --variations = \" wdth=drop \" "
# ifndef HB_EXPERIMENTAL_API
" \n \n Note: currently only full instancing is supported unless this util has been compiled with experimental api enabled. "
# endif