freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype][master] [truetype] Add support for `avar` table


From: Werner Lemberg (@wl)
Subject: [Git][freetype/freetype][master] [truetype] Add support for `avar` table 2.0 format.
Date: Fri, 04 Nov 2022 18:45:11 +0000

Werner Lemberg pushed to branch master at FreeType / FreeType

Commits:

  • ae4eb996
    by Behdad Esfahbod at 2022-11-04T19:44:36+01:00
    [truetype] Add support for `avar` table 2.0 format.
    
    See
    
      https://github.com/harfbuzz/boring-expansion-spec/blob/main/avar2.md
    
    for the specification.
    
    Currently, this is implemented only in most recent OS versions on Apple
    platforms and in the HarfBuzz library, but it is expected to be added to the
    OpenType standard soon.
    
    * src/truetype/ttgxvar.h (GX_AVarTableRec): New structure.
    (GX_BlendRec): Use it to replace `avar_segment` with `avar_table`.
    
    * src/truetype/ttgxvar.c (ft_var_load_avar): Load new table version.
    (ft_var_to_normalized, tt_done_blend): Extend for new format.
    (ft_var_load_hvvar, ft_var_to_design): Updated.
    

2 changed files:

Changes:

  • src/truetype/ttgxvar.c
    ... ... @@ -353,15 +353,21 @@
    353 353
       static void
    
    354 354
       ft_var_load_avar( TT_Face  face )
    
    355 355
       {
    
    356
    -    FT_Stream       stream = FT_FACE_STREAM( face );
    
    357
    -    FT_Memory       memory = stream->memory;
    
    356
    +    FT_Error   error;
    
    357
    +    FT_Stream  stream = FT_FACE_STREAM( face );
    
    358
    +    FT_Memory  memory = stream->memory;
    
    359
    +    FT_Int     i, j;
    
    360
    +
    
    358 361
         GX_Blend        blend  = face->blend;
    
    359 362
         GX_AVarSegment  segment;
    
    360
    -    FT_Error        error;
    
    361
    -    FT_Long         version;
    
    362
    -    FT_Long         axisCount;
    
    363
    -    FT_Int          i, j;
    
    364
    -    FT_ULong        table_len;
    
    363
    +    GX_AVarTable    table;
    
    364
    +
    
    365
    +    FT_Long   version;
    
    366
    +    FT_Long   axisCount;
    
    367
    +    FT_ULong  table_offset;
    
    368
    +    FT_ULong  table_len;
    
    369
    +    FT_ULong  store_offset;
    
    370
    +    FT_ULong  axisMap_offset;
    
    365 371
     
    
    366 372
     
    
    367 373
         FT_TRACE2(( "AVAR " ));
    
    ... ... @@ -374,13 +380,15 @@
    374 380
           return;
    
    375 381
         }
    
    376 382
     
    
    383
    +    table_offset = FT_STREAM_POS();
    
    384
    +
    
    377 385
         if ( FT_FRAME_ENTER( table_len ) )
    
    378 386
           return;
    
    379 387
     
    
    380 388
         version   = FT_GET_LONG();
    
    381 389
         axisCount = FT_GET_LONG();
    
    382 390
     
    
    383
    -    if ( version != 0x00010000L )
    
    391
    +    if ( version != 0x00010000L && version != 0x00020000L )
    
    384 392
         {
    
    385 393
           FT_TRACE2(( "bad table version\n" ));
    
    386 394
           goto Exit;
    
    ... ... @@ -396,10 +404,14 @@
    396 404
           goto Exit;
    
    397 405
         }
    
    398 406
     
    
    399
    -    if ( FT_QNEW_ARRAY( blend->avar_segment, axisCount ) )
    
    407
    +    if ( FT_NEW( blend->avar_table ) )
    
    408
    +      goto Exit;
    
    409
    +    table = blend->avar_table;
    
    410
    +
    
    411
    +    if ( FT_QNEW_ARRAY( table->avar_segment, axisCount ) )
    
    400 412
           goto Exit;
    
    401 413
     
    
    402
    -    segment = &blend->avar_segment[0];
    
    414
    +    segment = &table->avar_segment[0];
    
    403 415
         for ( i = 0; i < axisCount; i++, segment++ )
    
    404 416
         {
    
    405 417
           FT_TRACE5(( "  axis %d:\n", i ));
    
    ... ... @@ -412,9 +424,9 @@
    412 424
             /* it right now since loading the `avar' table is optional.   */
    
    413 425
     
    
    414 426
             for ( j = i - 1; j >= 0; j-- )
    
    415
    -          FT_FREE( blend->avar_segment[j].correspondence );
    
    427
    +          FT_FREE( table->avar_segment[j].correspondence );
    
    416 428
     
    
    417
    -        FT_FREE( blend->avar_segment );
    
    429
    +        FT_FREE( table->avar_segment );
    
    418 430
             goto Exit;
    
    419 431
           }
    
    420 432
     
    
    ... ... @@ -433,6 +445,35 @@
    433 445
           FT_TRACE5(( "\n" ));
    
    434 446
         }
    
    435 447
     
    
    448
    +    if ( version < 0x00020000L )
    
    449
    +      goto Exit;
    
    450
    +
    
    451
    +    axisMap_offset = FT_GET_ULONG();
    
    452
    +    store_offset   = FT_GET_ULONG();
    
    453
    +
    
    454
    +    if ( store_offset )
    
    455
    +    {
    
    456
    +      error = tt_var_load_item_variation_store(
    
    457
    +                face,
    
    458
    +                table_offset + store_offset,
    
    459
    +                &table->itemStore );
    
    460
    +      if ( error )
    
    461
    +        goto Exit;
    
    462
    +    }
    
    463
    +
    
    464
    +    if ( axisMap_offset )
    
    465
    +    {
    
    466
    +      error = tt_var_load_delta_set_index_mapping(
    
    467
    +                face,
    
    468
    +                table_offset + axisMap_offset,
    
    469
    +                &table->axisMap,
    
    470
    +                &table->itemStore,
    
    471
    +                table_len );
    
    472
    +      if ( error )
    
    473
    +        goto Exit;
    
    474
    +    }
    
    475
    +
    
    476
    +
    
    436 477
       Exit:
    
    437 478
         FT_FRAME_EXIT();
    
    438 479
       }
    
    ... ... @@ -888,12 +929,15 @@
    888 929
           table = blend->hvar_table;
    
    889 930
         }
    
    890 931
     
    
    891
    -    error = tt_var_load_item_variation_store(
    
    892
    -              face,
    
    893
    -              table_offset + store_offset,
    
    894
    -              &table->itemStore );
    
    895
    -    if ( error )
    
    896
    -      goto Exit;
    
    932
    +    if ( store_offset )
    
    933
    +    {
    
    934
    +      error = tt_var_load_item_variation_store(
    
    935
    +                face,
    
    936
    +                table_offset + store_offset,
    
    937
    +                &table->itemStore );
    
    938
    +      if ( error )
    
    939
    +        goto Exit;
    
    940
    +    }
    
    897 941
     
    
    898 942
         if ( widthMap_offset )
    
    899 943
         {
    
    ... ... @@ -1924,12 +1968,18 @@
    1924 1968
                             FT_Fixed*  coords,
    
    1925 1969
                             FT_Fixed*  normalized )
    
    1926 1970
       {
    
    1971
    +    FT_Error   error  = FT_Err_Ok;
    
    1972
    +    FT_Memory  memory = face->root.memory;
    
    1973
    +    FT_UInt    i, j;
    
    1974
    +
    
    1927 1975
         GX_Blend        blend;
    
    1928 1976
         FT_MM_Var*      mmvar;
    
    1929
    -    FT_UInt         i, j;
    
    1930 1977
         FT_Var_Axis*    a;
    
    1931 1978
         GX_AVarSegment  av;
    
    1932 1979
     
    
    1980
    +    FT_Fixed*  new_normalized;
    
    1981
    +    FT_Fixed*  old_normalized;
    
    1982
    +
    
    1933 1983
     
    
    1934 1984
         blend = face->blend;
    
    1935 1985
         mmvar = blend->mmvar;
    
    ... ... @@ -1980,30 +2030,91 @@
    1980 2030
         for ( ; i < mmvar->num_axis; i++ )
    
    1981 2031
           normalized[i] = 0;
    
    1982 2032
     
    
    1983
    -    if ( blend->avar_segment )
    
    2033
    +    if ( blend->avar_table )
    
    1984 2034
         {
    
    2035
    +      GX_AVarTable  table = blend->avar_table;
    
    2036
    +
    
    2037
    +
    
    1985 2038
           FT_TRACE5(( "normalized design coordinates"
    
    1986 2039
                       " before applying `avar' data:\n" ));
    
    1987 2040
     
    
    1988
    -      av = blend->avar_segment;
    
    1989
    -      for ( i = 0; i < mmvar->num_axis; i++, av++ )
    
    2041
    +      if ( table->avar_segment )
    
    1990 2042
           {
    
    1991
    -        for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
    
    2043
    +        av = table->avar_segment;
    
    2044
    +
    
    2045
    +        for ( i = 0; i < mmvar->num_axis; i++, av++ )
    
    1992 2046
             {
    
    1993
    -          if ( normalized[i] < av->correspondence[j].fromCoord )
    
    2047
    +          for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
    
    1994 2048
               {
    
    1995
    -            FT_TRACE5(( "  %.5f\n", normalized[i] / 65536.0 ));
    
    2049
    +            if ( normalized[i] < av->correspondence[j].fromCoord )
    
    2050
    +            {
    
    2051
    +              FT_TRACE5(( "  %.5f\n", normalized[i] / 65536.0 ));
    
    2052
    +
    
    2053
    +              normalized[i] =
    
    2054
    +                FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
    
    2055
    +                           av->correspondence[j].toCoord -
    
    2056
    +                             av->correspondence[j - 1].toCoord,
    
    2057
    +                           av->correspondence[j].fromCoord -
    
    2058
    +                             av->correspondence[j - 1].fromCoord ) +
    
    2059
    +                av->correspondence[j - 1].toCoord;
    
    2060
    +              break;
    
    2061
    +            }
    
    2062
    +          }
    
    2063
    +        }
    
    2064
    +      }
    
    1996 2065
     
    
    1997
    -            normalized[i] =
    
    1998
    -              FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
    
    1999
    -                         av->correspondence[j].toCoord -
    
    2000
    -                           av->correspondence[j - 1].toCoord,
    
    2001
    -                         av->correspondence[j].fromCoord -
    
    2002
    -                           av->correspondence[j - 1].fromCoord ) +
    
    2003
    -              av->correspondence[j - 1].toCoord;
    
    2004
    -            break;
    
    2066
    +      if ( table->itemStore.varData )
    
    2067
    +      {
    
    2068
    +        if ( FT_QNEW_ARRAY( new_normalized, mmvar->num_axis ) )
    
    2069
    +          return;
    
    2070
    +
    
    2071
    +        /* Install our half-normalized coordinates for the next */
    
    2072
    +        /* Item Variation Store to work with.                   */
    
    2073
    +        old_normalized                = face->blend->normalizedcoords;
    
    2074
    +        face->blend->normalizedcoords = normalized;
    
    2075
    +
    
    2076
    +        for ( i = 0; i < mmvar->num_axis; i++ )
    
    2077
    +        {
    
    2078
    +          FT_Fixed  v          = normalized[i];
    
    2079
    +          FT_UInt   innerIndex = i;
    
    2080
    +          FT_UInt   outerIndex = 0;
    
    2081
    +          FT_Int    delta;
    
    2082
    +
    
    2083
    +
    
    2084
    +          if ( table->axisMap.innerIndex )
    
    2085
    +          {
    
    2086
    +            FT_UInt  idx = i;
    
    2087
    +
    
    2088
    +
    
    2089
    +            if ( idx >= table->axisMap.mapCount )
    
    2090
    +              idx = table->axisMap.mapCount - 1;
    
    2091
    +
    
    2092
    +            outerIndex = table->axisMap.outerIndex[idx];
    
    2093
    +            innerIndex = table->axisMap.innerIndex[idx];
    
    2005 2094
               }
    
    2095
    +
    
    2096
    +          delta = tt_var_get_item_delta( face,
    
    2097
    +                                         &table->itemStore,
    
    2098
    +                                         outerIndex,
    
    2099
    +                                         innerIndex );
    
    2100
    +
    
    2101
    +	  v += delta << 2;
    
    2102
    +
    
    2103
    +	  /* Clamp value range. */
    
    2104
    +	  v = v >=  0x10000L ?  0x10000 : v;
    
    2105
    +	  v = v <= -0x10000L ? -0x10000 : v;
    
    2106
    +
    
    2107
    +          new_normalized[i] = v;
    
    2006 2108
             }
    
    2109
    +
    
    2110
    +        for ( i = 0; i < mmvar->num_axis; i++ )
    
    2111
    +        {
    
    2112
    +          normalized[i] = new_normalized[i];
    
    2113
    +        }
    
    2114
    +
    
    2115
    +        face->blend->normalizedcoords = old_normalized;
    
    2116
    +
    
    2117
    +        FT_FREE( new_normalized );
    
    2007 2118
           }
    
    2008 2119
         }
    
    2009 2120
       }
    
    ... ... @@ -2041,9 +2152,9 @@
    2041 2152
         for ( ; i < num_coords; i++ )
    
    2042 2153
           design[i] = 0;
    
    2043 2154
     
    
    2044
    -    if ( blend->avar_segment )
    
    2155
    +    if ( blend->avar_table && blend->avar_table->avar_segment )
    
    2045 2156
         {
    
    2046
    -      GX_AVarSegment  av = blend->avar_segment;
    
    2157
    +      GX_AVarSegment  av = blend->avar_table->avar_segment;
    
    2047 2158
     
    
    2048 2159
     
    
    2049 2160
           FT_TRACE5(( "design coordinates"
    
    ... ... @@ -4390,11 +4501,19 @@
    4390 4501
           FT_FREE( blend->normalized_stylecoords );
    
    4391 4502
           FT_FREE( blend->mmvar );
    
    4392 4503
     
    
    4393
    -      if ( blend->avar_segment )
    
    4504
    +      if ( blend->avar_table )
    
    4394 4505
           {
    
    4395 4506
             for ( i = 0; i < num_axes; i++ )
    
    4396
    -          FT_FREE( blend->avar_segment[i].correspondence );
    
    4397
    -        FT_FREE( blend->avar_segment );
    
    4507
    +          FT_FREE( blend->avar_table->avar_segment[i].correspondence );
    
    4508
    +        FT_FREE( blend->avar_table->avar_segment );
    
    4509
    +
    
    4510
    +        tt_var_done_item_variation_store( face,
    
    4511
    +                                          &blend->avar_table->itemStore );
    
    4512
    +
    
    4513
    +        tt_var_done_delta_set_index_map( face,
    
    4514
    +                                         &blend->avar_table->axisMap );
    
    4515
    +
    
    4516
    +        FT_FREE( blend->avar_table );
    
    4398 4517
           }
    
    4399 4518
     
    
    4400 4519
           if ( blend->hvar_table )
    

  • src/truetype/ttgxvar.h
    ... ... @@ -62,6 +62,23 @@ FT_BEGIN_HEADER
    62 62
       } GX_AVarSegmentRec, *GX_AVarSegment;
    
    63 63
     
    
    64 64
     
    
    65
    +  /**************************************************************************
    
    66
    +   *
    
    67
    +   * @Struct:
    
    68
    +   *   GX_AVarTableRec
    
    69
    +   *
    
    70
    +   * @Description:
    
    71
    +   *   Data from the `avar' table.
    
    72
    +   */
    
    73
    +  typedef struct  GX_AVarTableRec_
    
    74
    +  {
    
    75
    +    GX_AVarSegment        avar_segment;   /* avar_segment[num_axis] */
    
    76
    +    GX_ItemVarStoreRec    itemStore;      /* Item Variation Store   */
    
    77
    +    GX_DeltaSetIdxMapRec  axisMap;        /* Axis Mapping           */
    
    78
    +
    
    79
    +  } GX_AVarTableRec, *GX_AVarTable;
    
    80
    +
    
    81
    +
    
    65 82
       /**************************************************************************
    
    66 83
        *
    
    67 84
        * @Struct:
    
    ... ... @@ -194,7 +211,7 @@ FT_BEGIN_HEADER
    194 211
        *     A Boolean; if set, FreeType tried to load (and parse) the `avar'
    
    195 212
        *     table.
    
    196 213
        *
    
    197
    -   *   avar_segment ::
    
    214
    +   *   avar_table ::
    
    198 215
        *     Data from the `avar' table.
    
    199 216
        *
    
    200 217
        *   hvar_loaded ::
    
    ... ... @@ -259,7 +276,7 @@ FT_BEGIN_HEADER
    259 276
                           /* normalized_stylecoords[num_namedstyles][num_axis] */
    
    260 277
     
    
    261 278
         FT_Bool         avar_loaded;
    
    262
    -    GX_AVarSegment  avar_segment;                /* avar_segment[num_axis] */
    
    279
    +    GX_AVarTable    avar_table;
    
    263 280
     
    
    264 281
         FT_Bool         hvar_loaded;
    
    265 282
         FT_Bool         hvar_checked;
    


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]