Home | History | Annotate | Download | only in base
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftmm.c                                                                 */
      4 /*                                                                         */
      5 /*    Multiple Master font support (body).                                 */
      6 /*                                                                         */
      7 /*  Copyright 1996-2018 by                                                 */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18 
     19 #include <ft2build.h>
     20 #include FT_INTERNAL_DEBUG_H
     21 
     22 #include FT_MULTIPLE_MASTERS_H
     23 #include FT_INTERNAL_OBJECTS_H
     24 #include FT_SERVICE_MULTIPLE_MASTERS_H
     25 #include FT_SERVICE_METRICS_VARIATIONS_H
     26 
     27 
     28   /*************************************************************************/
     29   /*                                                                       */
     30   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     31   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     32   /* messages during execution.                                            */
     33   /*                                                                       */
     34 #undef  FT_COMPONENT
     35 #define FT_COMPONENT  trace_mm
     36 
     37 
     38   static FT_Error
     39   ft_face_get_mm_service( FT_Face                   face,
     40                           FT_Service_MultiMasters  *aservice )
     41   {
     42     FT_Error  error;
     43 
     44 
     45     *aservice = NULL;
     46 
     47     if ( !face )
     48       return FT_THROW( Invalid_Face_Handle );
     49 
     50     error = FT_ERR( Invalid_Argument );
     51 
     52     if ( FT_HAS_MULTIPLE_MASTERS( face ) )
     53     {
     54       FT_FACE_LOOKUP_SERVICE( face,
     55                               *aservice,
     56                               MULTI_MASTERS );
     57 
     58       if ( *aservice )
     59         error = FT_Err_Ok;
     60     }
     61 
     62     return error;
     63   }
     64 
     65 
     66   static FT_Error
     67   ft_face_get_mvar_service( FT_Face                        face,
     68                             FT_Service_MetricsVariations  *aservice )
     69   {
     70     FT_Error  error;
     71 
     72 
     73     *aservice = NULL;
     74 
     75     if ( !face )
     76       return FT_THROW( Invalid_Face_Handle );
     77 
     78     error = FT_ERR( Invalid_Argument );
     79 
     80     if ( FT_HAS_MULTIPLE_MASTERS( face ) )
     81     {
     82       FT_FACE_LOOKUP_SERVICE( face,
     83                               *aservice,
     84                               METRICS_VARIATIONS );
     85 
     86       if ( *aservice )
     87         error = FT_Err_Ok;
     88     }
     89 
     90     return error;
     91   }
     92 
     93 
     94   /* documentation is in ftmm.h */
     95 
     96   FT_EXPORT_DEF( FT_Error )
     97   FT_Get_Multi_Master( FT_Face           face,
     98                        FT_Multi_Master  *amaster )
     99   {
    100     FT_Error                 error;
    101     FT_Service_MultiMasters  service;
    102 
    103 
    104     /* check of `face' delayed to `ft_face_get_mm_service' */
    105 
    106     if ( !amaster )
    107       return FT_THROW( Invalid_Argument );
    108 
    109     error = ft_face_get_mm_service( face, &service );
    110     if ( !error )
    111     {
    112       error = FT_ERR( Invalid_Argument );
    113       if ( service->get_mm )
    114         error = service->get_mm( face, amaster );
    115     }
    116 
    117     return error;
    118   }
    119 
    120 
    121   /* documentation is in ftmm.h */
    122 
    123   FT_EXPORT_DEF( FT_Error )
    124   FT_Get_MM_Var( FT_Face      face,
    125                  FT_MM_Var*  *amaster )
    126   {
    127     FT_Error                 error;
    128     FT_Service_MultiMasters  service;
    129 
    130 
    131     /* check of `face' delayed to `ft_face_get_mm_service' */
    132 
    133     if ( !amaster )
    134       return FT_THROW( Invalid_Argument );
    135 
    136     error = ft_face_get_mm_service( face, &service );
    137     if ( !error )
    138     {
    139       error = FT_ERR( Invalid_Argument );
    140       if ( service->get_mm_var )
    141         error = service->get_mm_var( face, amaster );
    142     }
    143 
    144     return error;
    145   }
    146 
    147 
    148   /* documentation is in ftmm.h */
    149 
    150   FT_EXPORT_DEF( FT_Error )
    151   FT_Done_MM_Var( FT_Library  library,
    152                   FT_MM_Var*  amaster )
    153   {
    154     FT_Memory  memory;
    155 
    156 
    157     if ( !library )
    158       return FT_THROW( Invalid_Library_Handle );
    159 
    160     memory = library->memory;
    161     FT_FREE( amaster );
    162 
    163     return FT_Err_Ok;
    164   }
    165 
    166 
    167   /* documentation is in ftmm.h */
    168 
    169   FT_EXPORT_DEF( FT_Error )
    170   FT_Set_MM_Design_Coordinates( FT_Face   face,
    171                                 FT_UInt   num_coords,
    172                                 FT_Long*  coords )
    173   {
    174     FT_Error                 error;
    175     FT_Service_MultiMasters  service;
    176 
    177 
    178     /* check of `face' delayed to `ft_face_get_mm_service' */
    179 
    180     if ( num_coords && !coords )
    181       return FT_THROW( Invalid_Argument );
    182 
    183     error = ft_face_get_mm_service( face, &service );
    184     if ( !error )
    185     {
    186       error = FT_ERR( Invalid_Argument );
    187       if ( service->set_mm_design )
    188         error = service->set_mm_design( face, num_coords, coords );
    189     }
    190 
    191     /* enforce recomputation of auto-hinting data */
    192     if ( !error && face->autohint.finalizer )
    193     {
    194       face->autohint.finalizer( face->autohint.data );
    195       face->autohint.data = NULL;
    196     }
    197 
    198     return error;
    199   }
    200 
    201 
    202   /* documentation is in ftmm.h */
    203 
    204   FT_EXPORT_DEF( FT_Error )
    205   FT_Set_Var_Design_Coordinates( FT_Face    face,
    206                                  FT_UInt    num_coords,
    207                                  FT_Fixed*  coords )
    208   {
    209     FT_Error                      error;
    210     FT_Service_MultiMasters       service_mm   = NULL;
    211     FT_Service_MetricsVariations  service_mvar = NULL;
    212 
    213 
    214     /* check of `face' delayed to `ft_face_get_mm_service' */
    215 
    216     if ( num_coords && !coords )
    217       return FT_THROW( Invalid_Argument );
    218 
    219     error = ft_face_get_mm_service( face, &service_mm );
    220     if ( !error )
    221     {
    222       error = FT_ERR( Invalid_Argument );
    223       if ( service_mm->set_var_design )
    224         error = service_mm->set_var_design( face, num_coords, coords );
    225 
    226       /* internal error code -1 means `no change'; we can exit immediately */
    227       if ( error == -1 )
    228         return FT_Err_Ok;
    229     }
    230 
    231     if ( !error )
    232     {
    233       (void)ft_face_get_mvar_service( face, &service_mvar );
    234 
    235       if ( service_mvar && service_mvar->metrics_adjust )
    236         service_mvar->metrics_adjust( face );
    237     }
    238 
    239     /* enforce recomputation of auto-hinting data */
    240     if ( !error && face->autohint.finalizer )
    241     {
    242       face->autohint.finalizer( face->autohint.data );
    243       face->autohint.data = NULL;
    244     }
    245 
    246     return error;
    247   }
    248 
    249 
    250   /* documentation is in ftmm.h */
    251 
    252   FT_EXPORT_DEF( FT_Error )
    253   FT_Get_Var_Design_Coordinates( FT_Face    face,
    254                                  FT_UInt    num_coords,
    255                                  FT_Fixed*  coords )
    256   {
    257     FT_Error                 error;
    258     FT_Service_MultiMasters  service;
    259 
    260 
    261     /* check of `face' delayed to `ft_face_get_mm_service' */
    262 
    263     if ( !coords )
    264       return FT_THROW( Invalid_Argument );
    265 
    266     error = ft_face_get_mm_service( face, &service );
    267     if ( !error )
    268     {
    269       error = FT_ERR( Invalid_Argument );
    270       if ( service->get_var_design )
    271         error = service->get_var_design( face, num_coords, coords );
    272     }
    273 
    274     return error;
    275   }
    276 
    277 
    278   /* documentation is in ftmm.h */
    279 
    280   FT_EXPORT_DEF( FT_Error )
    281   FT_Set_MM_Blend_Coordinates( FT_Face    face,
    282                                FT_UInt    num_coords,
    283                                FT_Fixed*  coords )
    284   {
    285     FT_Error                      error;
    286     FT_Service_MultiMasters       service_mm   = NULL;
    287     FT_Service_MetricsVariations  service_mvar = NULL;
    288 
    289 
    290     /* check of `face' delayed to `ft_face_get_mm_service' */
    291 
    292     if ( num_coords && !coords )
    293       return FT_THROW( Invalid_Argument );
    294 
    295     error = ft_face_get_mm_service( face, &service_mm );
    296     if ( !error )
    297     {
    298       error = FT_ERR( Invalid_Argument );
    299       if ( service_mm->set_mm_blend )
    300         error = service_mm->set_mm_blend( face, num_coords, coords );
    301 
    302       /* internal error code -1 means `no change'; we can exit immediately */
    303       if ( error == -1 )
    304         return FT_Err_Ok;
    305     }
    306 
    307     if ( !error )
    308     {
    309       (void)ft_face_get_mvar_service( face, &service_mvar );
    310 
    311       if ( service_mvar && service_mvar->metrics_adjust )
    312         service_mvar->metrics_adjust( face );
    313     }
    314 
    315     /* enforce recomputation of auto-hinting data */
    316     if ( !error && face->autohint.finalizer )
    317     {
    318       face->autohint.finalizer( face->autohint.data );
    319       face->autohint.data = NULL;
    320     }
    321 
    322     return error;
    323   }
    324 
    325 
    326   /* documentation is in ftmm.h */
    327 
    328   /* This is exactly the same as the previous function.  It exists for */
    329   /* orthogonality.                                                    */
    330 
    331   FT_EXPORT_DEF( FT_Error )
    332   FT_Set_Var_Blend_Coordinates( FT_Face    face,
    333                                 FT_UInt    num_coords,
    334                                 FT_Fixed*  coords )
    335   {
    336     FT_Error                      error;
    337     FT_Service_MultiMasters       service_mm   = NULL;
    338     FT_Service_MetricsVariations  service_mvar = NULL;
    339 
    340 
    341     /* check of `face' delayed to `ft_face_get_mm_service' */
    342 
    343     if ( num_coords && !coords )
    344       return FT_THROW( Invalid_Argument );
    345 
    346     error = ft_face_get_mm_service( face, &service_mm );
    347     if ( !error )
    348     {
    349       error = FT_ERR( Invalid_Argument );
    350       if ( service_mm->set_mm_blend )
    351         error = service_mm->set_mm_blend( face, num_coords, coords );
    352 
    353       /* internal error code -1 means `no change'; we can exit immediately */
    354       if ( error == -1 )
    355         return FT_Err_Ok;
    356     }
    357 
    358     if ( !error )
    359     {
    360       (void)ft_face_get_mvar_service( face, &service_mvar );
    361 
    362       if ( service_mvar && service_mvar->metrics_adjust )
    363         service_mvar->metrics_adjust( face );
    364     }
    365 
    366     /* enforce recomputation of auto-hinting data */
    367     if ( !error && face->autohint.finalizer )
    368     {
    369       face->autohint.finalizer( face->autohint.data );
    370       face->autohint.data = NULL;
    371     }
    372 
    373     return error;
    374   }
    375 
    376 
    377   /* documentation is in ftmm.h */
    378 
    379   FT_EXPORT_DEF( FT_Error )
    380   FT_Get_MM_Blend_Coordinates( FT_Face    face,
    381                                FT_UInt    num_coords,
    382                                FT_Fixed*  coords )
    383   {
    384     FT_Error                 error;
    385     FT_Service_MultiMasters  service;
    386 
    387 
    388     /* check of `face' delayed to `ft_face_get_mm_service' */
    389 
    390     if ( !coords )
    391       return FT_THROW( Invalid_Argument );
    392 
    393     error = ft_face_get_mm_service( face, &service );
    394     if ( !error )
    395     {
    396       error = FT_ERR( Invalid_Argument );
    397       if ( service->get_mm_blend )
    398         error = service->get_mm_blend( face, num_coords, coords );
    399     }
    400 
    401     return error;
    402   }
    403 
    404 
    405   /* documentation is in ftmm.h */
    406 
    407   /* This is exactly the same as the previous function.  It exists for */
    408   /* orthogonality.                                                    */
    409 
    410   FT_EXPORT_DEF( FT_Error )
    411   FT_Get_Var_Blend_Coordinates( FT_Face    face,
    412                                 FT_UInt    num_coords,
    413                                 FT_Fixed*  coords )
    414   {
    415     FT_Error                 error;
    416     FT_Service_MultiMasters  service;
    417 
    418 
    419     /* check of `face' delayed to `ft_face_get_mm_service' */
    420 
    421     if ( !coords )
    422       return FT_THROW( Invalid_Argument );
    423 
    424     error = ft_face_get_mm_service( face, &service );
    425     if ( !error )
    426     {
    427       error = FT_ERR( Invalid_Argument );
    428       if ( service->get_mm_blend )
    429         error = service->get_mm_blend( face, num_coords, coords );
    430     }
    431 
    432     return error;
    433   }
    434 
    435 
    436   /* documentation is in ftmm.h */
    437 
    438   FT_EXPORT_DEF( FT_Error )
    439   FT_Get_Var_Axis_Flags( FT_MM_Var*  master,
    440                          FT_UInt     axis_index,
    441                          FT_UInt*    flags )
    442   {
    443     FT_UShort*  axis_flags;
    444 
    445 
    446     if ( !master || !flags )
    447       return FT_THROW( Invalid_Argument );
    448 
    449     if ( axis_index >= master->num_axis )
    450       return FT_THROW( Invalid_Argument );
    451 
    452     /* the axis flags array immediately follows the data of `master' */
    453     axis_flags = (FT_UShort*)&( master[1] );
    454     *flags     = axis_flags[axis_index];
    455 
    456     return FT_Err_Ok;
    457   }
    458 
    459 
    460   /* documentation is in ftmm.h */
    461 
    462   FT_EXPORT_DEF( FT_Error )
    463   FT_Set_Named_Instance( FT_Face  face,
    464                          FT_UInt  instance_index )
    465   {
    466     FT_Error  error;
    467 
    468     FT_Service_MultiMasters       service_mm   = NULL;
    469     FT_Service_MetricsVariations  service_mvar = NULL;
    470 
    471 
    472     /* check of `face' delayed to `ft_face_get_mm_service' */
    473 
    474     error = ft_face_get_mm_service( face, &service_mm );
    475     if ( !error )
    476     {
    477       error = FT_ERR( Invalid_Argument );
    478       if ( service_mm->set_instance )
    479         error = service_mm->set_instance( face, instance_index );
    480     }
    481 
    482     if ( !error )
    483     {
    484       (void)ft_face_get_mvar_service( face, &service_mvar );
    485 
    486       if ( service_mvar && service_mvar->metrics_adjust )
    487         service_mvar->metrics_adjust( face );
    488     }
    489 
    490     /* enforce recomputation of auto-hinting data */
    491     if ( !error && face->autohint.finalizer )
    492     {
    493       face->autohint.finalizer( face->autohint.data );
    494       face->autohint.data = NULL;
    495     }
    496 
    497     if ( !error )
    498     {
    499       face->face_index  = ( instance_index << 16 )        |
    500                           ( face->face_index & 0xFFFFL );
    501       face->face_flags &= ~FT_FACE_FLAG_VARIATION;
    502     }
    503 
    504     return error;
    505   }
    506 
    507 
    508 /* END */
    509