1 /***************************************************************************/ 2 /* */ 3 /* ftmm.c */ 4 /* */ 5 /* Multiple Master font support (body). */ 6 /* */ 7 /* Copyright 1996-2017 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 ft_face_get_mm_service(FT_Face face,FT_Service_MultiMasters * aservice)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 ft_face_get_mvar_service(FT_Face face,FT_Service_MetricsVariations * aservice)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 ) FT_Get_Multi_Master(FT_Face face,FT_Multi_Master * amaster)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 ) FT_Get_MM_Var(FT_Face face,FT_MM_Var ** amaster)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 ) FT_Set_MM_Design_Coordinates(FT_Face face,FT_UInt num_coords,FT_Long * coords)151 FT_Set_MM_Design_Coordinates( FT_Face face, 152 FT_UInt num_coords, 153 FT_Long* coords ) 154 { 155 FT_Error error; 156 FT_Service_MultiMasters service; 157 158 159 /* check of `face' delayed to `ft_face_get_mm_service' */ 160 161 if ( !coords ) 162 return FT_THROW( Invalid_Argument ); 163 164 error = ft_face_get_mm_service( face, &service ); 165 if ( !error ) 166 { 167 error = FT_ERR( Invalid_Argument ); 168 if ( service->set_mm_design ) 169 error = service->set_mm_design( face, num_coords, coords ); 170 } 171 172 /* enforce recomputation of auto-hinting data */ 173 if ( !error && face->autohint.finalizer ) 174 { 175 face->autohint.finalizer( face->autohint.data ); 176 face->autohint.data = NULL; 177 } 178 179 return error; 180 } 181 182 183 /* documentation is in ftmm.h */ 184 185 FT_EXPORT_DEF( FT_Error ) FT_Set_Var_Design_Coordinates(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)186 FT_Set_Var_Design_Coordinates( FT_Face face, 187 FT_UInt num_coords, 188 FT_Fixed* coords ) 189 { 190 FT_Error error; 191 FT_Service_MultiMasters service_mm; 192 FT_Service_MetricsVariations service_mvar; 193 194 195 /* check of `face' delayed to `ft_face_get_mm_service' */ 196 197 if ( !coords ) 198 return FT_THROW( Invalid_Argument ); 199 200 error = ft_face_get_mm_service( face, &service_mm ); 201 if ( !error ) 202 { 203 error = FT_ERR( Invalid_Argument ); 204 if ( service_mm->set_var_design ) 205 error = service_mm->set_var_design( face, num_coords, coords ); 206 } 207 208 if ( !error ) 209 error = ft_face_get_mvar_service( face, &service_mvar ); 210 211 if ( !error ) 212 { 213 if ( service_mvar->metrics_adjust ) 214 service_mvar->metrics_adjust( face ); 215 } 216 217 /* enforce recomputation of auto-hinting data */ 218 if ( !error && face->autohint.finalizer ) 219 { 220 face->autohint.finalizer( face->autohint.data ); 221 face->autohint.data = NULL; 222 } 223 224 return error; 225 } 226 227 228 /* documentation is in ftmm.h */ 229 230 FT_EXPORT_DEF( FT_Error ) FT_Get_Var_Design_Coordinates(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)231 FT_Get_Var_Design_Coordinates( FT_Face face, 232 FT_UInt num_coords, 233 FT_Fixed* coords ) 234 { 235 FT_Error error; 236 FT_Service_MultiMasters service; 237 238 239 /* check of `face' delayed to `ft_face_get_mm_service' */ 240 241 if ( !coords ) 242 return FT_THROW( Invalid_Argument ); 243 244 error = ft_face_get_mm_service( face, &service ); 245 if ( !error ) 246 { 247 error = FT_ERR( Invalid_Argument ); 248 if ( service->get_var_design ) 249 error = service->get_var_design( face, num_coords, coords ); 250 } 251 252 return error; 253 } 254 255 256 /* documentation is in ftmm.h */ 257 258 FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Blend_Coordinates(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)259 FT_Set_MM_Blend_Coordinates( FT_Face face, 260 FT_UInt num_coords, 261 FT_Fixed* coords ) 262 { 263 FT_Error error; 264 FT_Service_MultiMasters service_mm; 265 FT_Service_MetricsVariations service_mvar; 266 267 268 /* check of `face' delayed to `ft_face_get_mm_service' */ 269 270 if ( !coords ) 271 return FT_THROW( Invalid_Argument ); 272 273 error = ft_face_get_mm_service( face, &service_mm ); 274 if ( !error ) 275 { 276 error = FT_ERR( Invalid_Argument ); 277 if ( service_mm->set_mm_blend ) 278 error = service_mm->set_mm_blend( face, num_coords, coords ); 279 } 280 281 if ( !error ) 282 error = ft_face_get_mvar_service( face, &service_mvar ); 283 284 if ( !error ) 285 { 286 if ( service_mvar->metrics_adjust ) 287 service_mvar->metrics_adjust( face ); 288 } 289 290 /* enforce recomputation of auto-hinting data */ 291 if ( !error && face->autohint.finalizer ) 292 { 293 face->autohint.finalizer( face->autohint.data ); 294 face->autohint.data = NULL; 295 } 296 297 return error; 298 } 299 300 301 /* documentation is in ftmm.h */ 302 303 /* This is exactly the same as the previous function. It exists for */ 304 /* orthogonality. */ 305 306 FT_EXPORT_DEF( FT_Error ) FT_Set_Var_Blend_Coordinates(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)307 FT_Set_Var_Blend_Coordinates( FT_Face face, 308 FT_UInt num_coords, 309 FT_Fixed* coords ) 310 { 311 FT_Error error; 312 FT_Service_MultiMasters service_mm; 313 FT_Service_MetricsVariations service_mvar; 314 315 316 /* check of `face' delayed to `ft_face_get_mm_service' */ 317 318 if ( !coords ) 319 return FT_THROW( Invalid_Argument ); 320 321 error = ft_face_get_mm_service( face, &service_mm ); 322 if ( !error ) 323 { 324 error = FT_ERR( Invalid_Argument ); 325 if ( service_mm->set_mm_blend ) 326 error = service_mm->set_mm_blend( face, num_coords, coords ); 327 } 328 329 if ( !error ) 330 error = ft_face_get_mvar_service( face, &service_mvar ); 331 332 if ( !error ) 333 { 334 if ( service_mvar->metrics_adjust ) 335 service_mvar->metrics_adjust( face ); 336 } 337 338 /* enforce recomputation of auto-hinting data */ 339 if ( !error && face->autohint.finalizer ) 340 { 341 face->autohint.finalizer( face->autohint.data ); 342 face->autohint.data = NULL; 343 } 344 345 return error; 346 } 347 348 349 /* documentation is in ftmm.h */ 350 351 FT_EXPORT_DEF( FT_Error ) FT_Get_MM_Blend_Coordinates(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)352 FT_Get_MM_Blend_Coordinates( FT_Face face, 353 FT_UInt num_coords, 354 FT_Fixed* coords ) 355 { 356 FT_Error error; 357 FT_Service_MultiMasters service; 358 359 360 /* check of `face' delayed to `ft_face_get_mm_service' */ 361 362 if ( !coords ) 363 return FT_THROW( Invalid_Argument ); 364 365 error = ft_face_get_mm_service( face, &service ); 366 if ( !error ) 367 { 368 error = FT_ERR( Invalid_Argument ); 369 if ( service->get_mm_blend ) 370 error = service->get_mm_blend( face, num_coords, coords ); 371 } 372 373 return error; 374 } 375 376 377 /* documentation is in ftmm.h */ 378 379 /* This is exactly the same as the previous function. It exists for */ 380 /* orthogonality. */ 381 382 FT_EXPORT_DEF( FT_Error ) FT_Get_Var_Blend_Coordinates(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)383 FT_Get_Var_Blend_Coordinates( FT_Face face, 384 FT_UInt num_coords, 385 FT_Fixed* coords ) 386 { 387 FT_Error error; 388 FT_Service_MultiMasters service; 389 390 391 /* check of `face' delayed to `ft_face_get_mm_service' */ 392 393 if ( !coords ) 394 return FT_THROW( Invalid_Argument ); 395 396 error = ft_face_get_mm_service( face, &service ); 397 if ( !error ) 398 { 399 error = FT_ERR( Invalid_Argument ); 400 if ( service->get_mm_blend ) 401 error = service->get_mm_blend( face, num_coords, coords ); 402 } 403 404 return error; 405 } 406 407 408 /* END */ 409