tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ttcolr.c (62186B)


      1 /****************************************************************************
      2 *
      3 * ttcolr.c
      4 *
      5 *   TrueType and OpenType colored glyph layer support (body).
      6 *
      7 * Copyright (C) 2018-2025 by
      8 * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
      9 *
     10 * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
     11 *
     12 * This file is part of the FreeType project, and may only be used,
     13 * modified, and distributed under the terms of the FreeType project
     14 * license, LICENSE.TXT.  By continuing to use, modify, or distribute
     15 * this file you indicate that you have read the license and
     16 * understand and accept it fully.
     17 *
     18 */
     19 
     20 
     21  /**************************************************************************
     22   *
     23   * `COLR' table specification:
     24   *
     25   *   https://www.microsoft.com/typography/otspec/colr.htm
     26   *
     27   */
     28 
     29 
     30 #include <freetype/internal/ftcalc.h>
     31 #include <freetype/internal/ftdebug.h>
     32 #include <freetype/internal/ftstream.h>
     33 #include <freetype/tttags.h>
     34 #include <freetype/ftcolor.h>
     35 #include <freetype/config/integer-types.h>
     36 
     37 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     38 #include <freetype/internal/services/svmm.h>
     39 #endif
     40 
     41 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
     42 
     43 #include "ttcolr.h"
     44 
     45 
     46  /* NOTE: These are the table sizes calculated through the specs. */
     47 #define BASE_GLYPH_SIZE                   6U
     48 #define BASE_GLYPH_PAINT_RECORD_SIZE      6U
     49 #define LAYER_V1_LIST_PAINT_OFFSET_SIZE   4U
     50 #define LAYER_V1_LIST_NUM_LAYERS_SIZE     4U
     51 #define COLOR_STOP_SIZE                   6U
     52 #define VAR_IDX_BASE_SIZE                 4U
     53 #define LAYER_SIZE                        4U
     54 /* https://learn.microsoft.com/typography/opentype/spec/colr#colr-header */
     55 /* 3 * uint16 + 2 * Offset32 */
     56 #define COLRV0_HEADER_SIZE               14U
     57 /* COLRV0_HEADER_SIZE + 5 * Offset32 */
     58 #define COLRV1_HEADER_SIZE               34U
     59 
     60 
     61 #define ENSURE_READ_BYTES( byte_size )                             \
     62  if ( p < colr->paints_start_v1                                || \
     63       p > (FT_Byte*)colr->table + colr->table_size - byte_size )  \
     64    return 0
     65 
     66 
     67  typedef enum  FT_PaintFormat_Internal_
     68  {
     69    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID                = 3,
     70    FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT      = 5,
     71    FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT      = 7,
     72    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT       = 9,
     73    FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM            = 13,
     74    FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE            = 15,
     75    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE                = 17,
     76    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER             = 18,
     77    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER         = 19,
     78    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM            = 20,
     79    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM        = 21,
     80    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER     = 22,
     81    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER = 23,
     82    FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE               = 25,
     83    FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER            = 26,
     84    FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER        = 27,
     85    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW                 = 29,
     86    FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER              = 30,
     87    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER          = 31,
     88 
     89  } FT_PaintFormat_Internal;
     90 
     91 
     92  typedef struct  BaseGlyphRecord_
     93  {
     94    FT_UShort  gid;
     95    FT_UShort  first_layer_index;
     96    FT_UShort  num_layers;
     97 
     98  } BaseGlyphRecord;
     99 
    100 
    101  typedef struct  BaseGlyphV1Record_
    102  {
    103    FT_UShort  gid;
    104    /* Offset from start of BaseGlyphV1List, i.e., from base_glyphs_v1. */
    105    FT_ULong   paint_offset;
    106 
    107  } BaseGlyphV1Record;
    108 
    109 
    110  typedef struct  Colr_
    111  {
    112    FT_UShort  version;
    113    FT_UShort  num_base_glyphs;
    114    FT_UShort  num_layers;
    115 
    116    FT_Byte*  base_glyphs;
    117    FT_Byte*  layers;
    118 
    119    FT_ULong  num_base_glyphs_v1;
    120    /* Points at beginning of BaseGlyphV1List. */
    121    FT_Byte*  base_glyphs_v1;
    122 
    123    FT_ULong  num_layers_v1;
    124    FT_Byte*  layers_v1;
    125 
    126    FT_Byte*  clip_list;
    127 
    128    /*
    129     * Paint tables start at the minimum of the end of the LayerList and the
    130     * end of the BaseGlyphList.  Record this location in a field here for
    131     * safety checks when accessing paint tables.
    132     */
    133    FT_Byte*  paints_start_v1;
    134 
    135 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    136    /* Item Variation Store for variable 'COLR' v1. */
    137    GX_ItemVarStoreRec    var_store;
    138    GX_DeltaSetIdxMapRec  delta_set_idx_map;
    139 #endif
    140 
    141    /* The memory that backs up the `COLR' table. */
    142    void*     table;
    143    FT_ULong  table_size;
    144 
    145  } Colr;
    146 
    147 
    148  /**************************************************************************
    149   *
    150   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    151   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
    152   * messages during execution.
    153   */
    154 #undef  FT_COMPONENT
    155 #define FT_COMPONENT  ttcolr
    156 
    157 
    158  FT_LOCAL_DEF( FT_Error )
    159  tt_face_load_colr( TT_Face    face,
    160                     FT_Stream  stream )
    161  {
    162    FT_Error   error;
    163    FT_Memory  memory = face->root.memory;
    164 
    165    FT_Byte*  table = NULL;
    166    FT_Byte*  p     = NULL;
    167    /* Needed for reading array lengths in referenced tables. */
    168    FT_Byte*  p1    = NULL;
    169 
    170    Colr*  colr = NULL;
    171 
    172    FT_ULong  base_glyph_offset, layer_offset;
    173    FT_ULong  base_glyphs_offset_v1, num_base_glyphs_v1;
    174    FT_ULong  layer_offset_v1, num_layers_v1, clip_list_offset;
    175    FT_ULong  table_size;
    176 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    177    FT_ULong  colr_offset_in_stream;
    178 #endif
    179 
    180 
    181    /* `COLR' always needs `CPAL' */
    182    if ( !face->cpal )
    183      return FT_THROW( Invalid_File_Format );
    184 
    185    error = face->goto_table( face, TTAG_COLR, stream, &table_size );
    186    if ( error )
    187      goto NoColr;
    188 
    189 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    190    colr_offset_in_stream = FT_STREAM_POS();
    191 #endif
    192 
    193    if ( table_size < COLRV0_HEADER_SIZE )
    194      goto NoColr;
    195 
    196    if ( FT_FRAME_EXTRACT( table_size, table ) )
    197      goto NoColr;
    198 
    199    p = table;
    200 
    201    if ( FT_NEW( colr ) )
    202      goto NoColr;
    203 
    204    colr->version = FT_NEXT_USHORT( p );
    205    if ( colr->version != 0 && colr->version != 1 )
    206      goto InvalidTable;
    207 
    208    colr->num_base_glyphs = FT_NEXT_USHORT( p );
    209    base_glyph_offset     = FT_NEXT_ULONG( p );
    210 
    211    if ( table_size <= base_glyph_offset )
    212      goto InvalidTable;
    213    if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE
    214             < colr->num_base_glyphs )
    215      goto InvalidTable;
    216 
    217    layer_offset     = FT_NEXT_ULONG( p );
    218    colr->num_layers = FT_NEXT_USHORT( p );
    219 
    220    if ( table_size <= layer_offset )
    221      goto InvalidTable;
    222    if ( ( table_size - layer_offset ) / LAYER_SIZE
    223             < colr->num_layers )
    224      goto InvalidTable;
    225 
    226    if ( colr->version == 1 )
    227    {
    228      if ( table_size < COLRV1_HEADER_SIZE )
    229        goto InvalidTable;
    230 
    231      base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
    232 
    233      if ( table_size - 4 <= base_glyphs_offset_v1 )
    234        goto InvalidTable;
    235 
    236      p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
    237      num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
    238 
    239      if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
    240               < num_base_glyphs_v1 )
    241        goto InvalidTable;
    242 
    243      colr->num_base_glyphs_v1 = num_base_glyphs_v1;
    244      colr->base_glyphs_v1     = p1;
    245 
    246      layer_offset_v1 = FT_NEXT_ULONG( p );
    247 
    248      if ( table_size <= layer_offset_v1 )
    249        goto InvalidTable;
    250 
    251      if ( layer_offset_v1 )
    252      {
    253        if ( table_size - 4 <= layer_offset_v1 )
    254          goto InvalidTable;
    255 
    256        p1            = (FT_Byte*)( table + layer_offset_v1 );
    257        num_layers_v1 = FT_PEEK_ULONG( p1 );
    258 
    259        if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE
    260                < num_layers_v1 )
    261          goto InvalidTable;
    262 
    263        colr->num_layers_v1 = num_layers_v1;
    264        colr->layers_v1     = p1;
    265 
    266        colr->paints_start_v1 =
    267            FT_MIN( colr->base_glyphs_v1 +
    268                    colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE,
    269                    colr->layers_v1 +
    270                    colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE );
    271      }
    272      else
    273      {
    274        colr->num_layers_v1   = 0;
    275        colr->layers_v1       = 0;
    276        colr->paints_start_v1 =
    277          colr->base_glyphs_v1 +
    278          colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE;
    279      }
    280 
    281      clip_list_offset = FT_NEXT_ULONG( p );
    282 
    283      if ( table_size <= clip_list_offset )
    284        goto InvalidTable;
    285 
    286      if ( clip_list_offset )
    287        colr->clip_list = (FT_Byte*)( table + clip_list_offset );
    288      else
    289        colr->clip_list = 0;
    290 
    291 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    292      colr->var_store.dataCount     = 0;
    293      colr->var_store.varData       = NULL;
    294      colr->var_store.axisCount     = 0;
    295      colr->var_store.regionCount   = 0;
    296      colr->var_store.varRegionList = 0;
    297 
    298      colr->delta_set_idx_map.mapCount   = 0;
    299      colr->delta_set_idx_map.outerIndex = NULL;
    300      colr->delta_set_idx_map.innerIndex = NULL;
    301 
    302      if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR )
    303      {
    304        FT_ULong  var_idx_map_offset, var_store_offset;
    305 
    306        FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    307 
    308 
    309        var_idx_map_offset = FT_NEXT_ULONG( p );
    310 
    311        if ( var_idx_map_offset >= table_size )
    312          goto InvalidTable;
    313 
    314        var_store_offset = FT_NEXT_ULONG( p );
    315        if ( table_size <= var_store_offset )
    316          goto InvalidTable;
    317 
    318        if ( var_store_offset )
    319        {
    320          /* If variation info has not been initialized yet, try doing so, */
    321          /* otherwise loading the variation store will fail as it         */
    322          /* requires access to `blend` for checking the number of axes.   */
    323          if ( !face->blend )
    324            if ( mm->get_mm_var( FT_FACE( face ), NULL ) )
    325              goto InvalidTable;
    326 
    327          /* Try loading `VarIdxMap` and `VarStore`. */
    328          error = mm->load_item_var_store(
    329                    FT_FACE( face ),
    330                    colr_offset_in_stream + var_store_offset,
    331                    &colr->var_store );
    332          if ( error != FT_Err_Ok )
    333            goto InvalidTable;
    334        }
    335 
    336        if ( colr->var_store.axisCount && var_idx_map_offset )
    337        {
    338          error = mm->load_delta_set_idx_map(
    339                    FT_FACE( face ),
    340                    colr_offset_in_stream + var_idx_map_offset,
    341                    &colr->delta_set_idx_map,
    342                    &colr->var_store,
    343                    table_size );
    344          if ( error != FT_Err_Ok )
    345            goto InvalidTable;
    346        }
    347      }
    348 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    349    }
    350 
    351    colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );
    352    colr->layers      = (FT_Byte*)( table + layer_offset      );
    353    colr->table       = table;
    354    colr->table_size  = table_size;
    355 
    356    face->colr = colr;
    357 
    358    return FT_Err_Ok;
    359 
    360  InvalidTable:
    361 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    362    {
    363      FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    364 
    365 
    366      mm->done_delta_set_idx_map( FT_FACE( face ),
    367                                  &colr->delta_set_idx_map );
    368      mm->done_item_var_store( FT_FACE( face ),
    369                               &colr->var_store );
    370    }
    371 #endif
    372 
    373    error = FT_THROW( Invalid_Table );
    374 
    375  NoColr:
    376    FT_FRAME_RELEASE( table );
    377    FT_FREE( colr );
    378 
    379    return error;
    380  }
    381 
    382 
    383  FT_LOCAL_DEF( void )
    384  tt_face_free_colr( TT_Face  face )
    385  {
    386    FT_Stream  stream = face->root.stream;
    387    FT_Memory  memory = face->root.memory;
    388 
    389    Colr*  colr = (Colr*)face->colr;
    390 
    391 
    392    if ( colr )
    393    {
    394 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    395      {
    396        FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    397 
    398 
    399        mm->done_delta_set_idx_map( FT_FACE( face ),
    400                                    &colr->delta_set_idx_map );
    401        mm->done_item_var_store( FT_FACE( face ),
    402                                 &colr->var_store );
    403      }
    404 #endif
    405      FT_FRAME_RELEASE( colr->table );
    406      FT_FREE( colr );
    407    }
    408  }
    409 
    410 
    411  static FT_Bool
    412  find_base_glyph_record( FT_Byte*          base_glyph_begin,
    413                          FT_UInt           num_base_glyph,
    414                          FT_UInt           glyph_id,
    415                          BaseGlyphRecord*  record )
    416  {
    417    FT_UInt  min = 0;
    418    FT_UInt  max = num_base_glyph;
    419 
    420 
    421    while ( min < max )
    422    {
    423      FT_UInt   mid = min + ( max - min ) / 2;
    424      FT_Byte*  p   = base_glyph_begin + mid * BASE_GLYPH_SIZE;
    425 
    426      FT_UShort  gid = FT_NEXT_USHORT( p );
    427 
    428 
    429      if ( gid < glyph_id )
    430        min = mid + 1;
    431      else if (gid > glyph_id )
    432        max = mid;
    433      else
    434      {
    435        record->gid               = gid;
    436        record->first_layer_index = FT_NEXT_USHORT( p );
    437        record->num_layers        = FT_NEXT_USHORT( p );
    438 
    439        return 1;
    440      }
    441    }
    442 
    443    return 0;
    444  }
    445 
    446 
    447  FT_LOCAL_DEF( FT_Bool )
    448  tt_face_get_colr_layer( TT_Face            face,
    449                          FT_UInt            base_glyph,
    450                          FT_UInt           *aglyph_index,
    451                          FT_UInt           *acolor_index,
    452                          FT_LayerIterator*  iterator )
    453  {
    454    Colr*            colr = (Colr*)face->colr;
    455    BaseGlyphRecord  glyph_record;
    456 
    457 
    458    if ( !colr )
    459      return 0;
    460 
    461    if ( !iterator->p )
    462    {
    463      FT_ULong  offset;
    464 
    465 
    466      /* first call to function */
    467      iterator->layer = 0;
    468 
    469      if ( !find_base_glyph_record( colr->base_glyphs,
    470                                    colr->num_base_glyphs,
    471                                    base_glyph,
    472                                    &glyph_record ) )
    473        return 0;
    474 
    475      if ( glyph_record.num_layers )
    476        iterator->num_layers = glyph_record.num_layers;
    477      else
    478        return 0;
    479 
    480      offset = LAYER_SIZE * glyph_record.first_layer_index;
    481      if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size )
    482        return 0;
    483 
    484      iterator->p = colr->layers + offset;
    485    }
    486 
    487    if ( iterator->layer >= iterator->num_layers                     ||
    488         iterator->p < colr->layers                                  ||
    489         iterator->p >= ( (FT_Byte*)colr->table + colr->table_size ) )
    490      return 0;
    491 
    492    *aglyph_index = FT_NEXT_USHORT( iterator->p );
    493    *acolor_index = FT_NEXT_USHORT( iterator->p );
    494 
    495    if ( *aglyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs )   ||
    496         ( *acolor_index != 0xFFFF                                 &&
    497           *acolor_index >= face->palette_data.num_palette_entries ) )
    498      return 0;
    499 
    500    iterator->layer++;
    501 
    502    return 1;
    503  }
    504 
    505 
    506  static FT_Bool
    507  read_color_line( Colr*          colr,
    508                   FT_Byte*       color_line_p,
    509                   FT_ColorLine*  colorline,
    510                   FT_Bool        read_variable )
    511  {
    512    FT_Byte*        p = color_line_p;
    513    FT_PaintExtend  paint_extend;
    514 
    515 
    516    ENSURE_READ_BYTES( 3 );
    517 
    518    paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p );
    519    if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT )
    520      return 0;
    521 
    522    colorline->extend = paint_extend;
    523 
    524    colorline->color_stop_iterator.num_color_stops    = FT_NEXT_USHORT( p );
    525    colorline->color_stop_iterator.p                  = p;
    526    colorline->color_stop_iterator.current_color_stop = 0;
    527    colorline->color_stop_iterator.read_variable      = read_variable;
    528 
    529    return 1;
    530  }
    531 
    532 
    533  /*
    534   * Read a paint offset for `FT_Paint*` objects that have them and check
    535   * whether it is within reasonable limits within the font and the COLR
    536   * table.
    537   *
    538   * Return 1 on success, 0 on failure.
    539   */
    540  static FT_Bool
    541  get_child_table_pointer ( Colr*      colr,
    542                            FT_Byte*   paint_base,
    543                            FT_Byte**  p,
    544                            FT_Byte**  child_table_pointer )
    545  {
    546    FT_UInt32  paint_offset;
    547    FT_Byte*   child_table_p;
    548 
    549 
    550    if ( !child_table_pointer )
    551      return 0;
    552 
    553    if ( *p < colr->paints_start_v1                            ||
    554         *p > (FT_Byte*)colr->table + colr->table_size - 1 - 3 )
    555      return 0;
    556 
    557    paint_offset = FT_NEXT_UOFF3( *p );
    558    if ( !paint_offset )
    559      return 0;
    560 
    561    child_table_p = (FT_Byte*)( paint_base + paint_offset );
    562 
    563    if ( child_table_p < colr->paints_start_v1                         ||
    564         child_table_p >= ( (FT_Byte*)colr->table + colr->table_size ) )
    565      return 0;
    566 
    567    *child_table_pointer = child_table_p;
    568    return 1;
    569  }
    570 
    571 
    572 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    573 
    574  static FT_Bool
    575  get_deltas_for_var_index_base ( TT_Face           face,
    576                                  Colr*             colr,
    577                                  FT_ULong          var_index_base,
    578                                  FT_UInt           num_deltas,
    579                                  FT_ItemVarDelta*  deltas )
    580  {
    581    FT_UInt   outer_index    = 0;
    582    FT_UInt   inner_index    = 0;
    583    FT_ULong  loop_var_index = var_index_base;
    584 
    585    FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
    586 
    587    FT_UInt  i = 0;
    588 
    589 
    590    if ( var_index_base == 0xFFFFFFFF )
    591    {
    592      for ( i = 0; i < num_deltas; ++i )
    593        deltas[i] = 0;
    594      return 1;
    595    }
    596 
    597    for ( i = 0; i < num_deltas; ++i )
    598    {
    599      loop_var_index = var_index_base + i;
    600 
    601      if ( colr->delta_set_idx_map.innerIndex )
    602      {
    603        if ( loop_var_index >= colr->delta_set_idx_map.mapCount )
    604          loop_var_index = colr->delta_set_idx_map.mapCount - 1;
    605 
    606        outer_index = colr->delta_set_idx_map.outerIndex[loop_var_index];
    607        inner_index = colr->delta_set_idx_map.innerIndex[loop_var_index];
    608      }
    609      else
    610      {
    611        outer_index = 0;
    612        inner_index = loop_var_index;
    613      }
    614 
    615      deltas[i] = mm->get_item_delta( FT_FACE( face ), &colr->var_store,
    616                                      outer_index, inner_index );
    617    }
    618 
    619    return 1;
    620  }
    621 
    622 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    623 
    624 
    625  static FT_Bool
    626  read_paint( TT_Face         face,
    627              Colr*           colr,
    628              FT_Byte*        p,
    629              FT_COLR_Paint*  apaint )
    630  {
    631    FT_Byte*  paint_base    = p;
    632    FT_Byte*  child_table_p = NULL;
    633    FT_Bool   do_read_var   = FALSE;
    634 
    635 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    636    FT_ULong         var_index_base = 0;
    637    /* Longest varIndexBase offset is 5 in the spec. */
    638    FT_ItemVarDelta  item_deltas[6] = { 0, 0, 0, 0, 0, 0 };
    639 #else
    640    FT_UNUSED( face );
    641 #endif
    642 
    643 
    644    if ( !p || !colr || !colr->table )
    645      return 0;
    646 
    647    /* The last byte of the 'COLR' table is at 'size-1'; subtract 1 of    */
    648    /* that to account for the expected format byte we are going to read. */
    649    if ( p < colr->paints_start_v1                        ||
    650         p > (FT_Byte*)colr->table + colr->table_size - 2 )
    651      return 0;
    652 
    653    apaint->format = (FT_PaintFormat)FT_NEXT_BYTE( p );
    654 
    655    if ( apaint->format >= FT_COLR_PAINT_FORMAT_MAX )
    656      return 0;
    657 
    658    if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_LAYERS )
    659    {
    660      /* Initialize layer iterator/ */
    661      FT_Byte    num_layers;
    662      FT_UInt32  first_layer_index;
    663 
    664 
    665      ENSURE_READ_BYTES( 5 );
    666      num_layers = FT_NEXT_BYTE( p );
    667      if ( num_layers > colr->num_layers_v1 )
    668        return 0;
    669 
    670      first_layer_index = FT_NEXT_ULONG( p );
    671      if ( first_layer_index + num_layers > colr->num_layers_v1 )
    672        return 0;
    673 
    674      apaint->u.colr_layers.layer_iterator.num_layers = num_layers;
    675      apaint->u.colr_layers.layer_iterator.layer      = 0;
    676      /* TODO: Check whether pointer is outside colr? */
    677      apaint->u.colr_layers.layer_iterator.p =
    678        colr->layers_v1 +
    679        LAYER_V1_LIST_NUM_LAYERS_SIZE +
    680        LAYER_V1_LIST_PAINT_OFFSET_SIZE * first_layer_index;
    681 
    682      return 1;
    683    }
    684 
    685    else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID ||
    686              (FT_PaintFormat_Internal)apaint->format ==
    687                 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID   )
    688    {
    689      ENSURE_READ_BYTES( 4 );
    690      apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p );
    691      apaint->u.solid.color.alpha         = FT_NEXT_SHORT( p );
    692 
    693 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    694      if ( (FT_PaintFormat_Internal)apaint->format ==
    695              FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID )
    696      {
    697        ENSURE_READ_BYTES( 4 );
    698        var_index_base = FT_NEXT_ULONG( p );
    699 
    700        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1,
    701                                             item_deltas ) )
    702          return 0;
    703 
    704        apaint->u.solid.color.alpha += (FT_F2Dot14)item_deltas[0];
    705      }
    706 #endif
    707 
    708      apaint->format = FT_COLR_PAINTFORMAT_SOLID;
    709 
    710      return 1;
    711    }
    712 
    713    else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
    714    {
    715      ENSURE_READ_BYTES(2);
    716      apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
    717 
    718      return 1;
    719    }
    720 
    721    /*
    722     * Grouped below here are all paint formats that have an offset to a
    723     * child paint table as the first entry (for example, a color line or a
    724     * child paint table).  Retrieve that and determine whether that paint
    725     * offset is valid first.
    726     */
    727 
    728    if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
    729      return 0;
    730 
    731    if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT      ||
    732         ( do_read_var =
    733             ( (FT_PaintFormat_Internal)apaint->format ==
    734               FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT ) ) )
    735    {
    736      if ( !read_color_line( colr,
    737                             child_table_p,
    738                             &apaint->u.linear_gradient.colorline,
    739                             do_read_var ) )
    740        return 0;
    741 
    742      /*
    743       * In order to support variations expose these as FT_Fixed 16.16
    744       * values so that we can support fractional values after
    745       * interpolation.
    746       */
    747      ENSURE_READ_BYTES( 12 );
    748      apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    749      apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    750      apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    751      apaint->u.linear_gradient.p1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    752      apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    753      apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    754 
    755 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    756      if ( do_read_var )
    757      {
    758        ENSURE_READ_BYTES( 4 );
    759        var_index_base = FT_NEXT_ULONG ( p );
    760 
    761        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6,
    762                                             item_deltas ) )
    763          return 0;
    764 
    765        apaint->u.linear_gradient.p0.x += INT_TO_FIXED( item_deltas[0] );
    766        apaint->u.linear_gradient.p0.y += INT_TO_FIXED( item_deltas[1] );
    767        apaint->u.linear_gradient.p1.x += INT_TO_FIXED( item_deltas[2] );
    768        apaint->u.linear_gradient.p1.y += INT_TO_FIXED( item_deltas[3] );
    769        apaint->u.linear_gradient.p2.x += INT_TO_FIXED( item_deltas[4] );
    770        apaint->u.linear_gradient.p2.y += INT_TO_FIXED( item_deltas[5] );
    771      }
    772 #endif
    773 
    774      apaint->format = FT_COLR_PAINTFORMAT_LINEAR_GRADIENT;
    775 
    776      return 1;
    777    }
    778 
    779    else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT      ||
    780              ( do_read_var =
    781                  ( (FT_PaintFormat_Internal)apaint->format ==
    782                    FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT ) ) )
    783    {
    784      FT_Pos  tmp;
    785 
    786 
    787      if ( !read_color_line( colr,
    788                             child_table_p,
    789                             &apaint->u.radial_gradient.colorline,
    790                             do_read_var ) )
    791        return 0;
    792 
    793 
    794      /* In the OpenType specification, `r0` and `r1` are defined as   */
    795      /* `UFWORD`.  Since FreeType doesn't have a corresponding 16.16  */
    796      /* format we convert to `FWORD` and replace negative values with */
    797      /* (32bit) `FT_INT_MAX`.                                         */
    798 
    799      ENSURE_READ_BYTES( 12 );
    800 
    801      apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    802      apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    803 
    804      tmp                          = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    805      apaint->u.radial_gradient.r0 = tmp < 0 ? FT_INT_MAX : tmp;
    806 
    807      apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    808      apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    809 
    810      tmp                          = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    811      apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp;
    812 
    813 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    814      if ( do_read_var )
    815      {
    816        ENSURE_READ_BYTES( 4 );
    817        var_index_base = FT_NEXT_ULONG ( p );
    818 
    819        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6,
    820                                             item_deltas ) )
    821          return 0;
    822 
    823        apaint->u.radial_gradient.c0.x += INT_TO_FIXED( item_deltas[0] );
    824        apaint->u.radial_gradient.c0.y += INT_TO_FIXED( item_deltas[1] );
    825 
    826        // TODO: Anything to be done about UFWORD deltas here?
    827        apaint->u.radial_gradient.r0 += INT_TO_FIXED( item_deltas[2] );
    828 
    829        apaint->u.radial_gradient.c1.x += INT_TO_FIXED( item_deltas[3] );
    830        apaint->u.radial_gradient.c1.y += INT_TO_FIXED( item_deltas[4] );
    831 
    832        apaint->u.radial_gradient.r1 += INT_TO_FIXED( item_deltas[5] );
    833      }
    834 #endif
    835 
    836      apaint->format = FT_COLR_PAINTFORMAT_RADIAL_GRADIENT;
    837 
    838      return 1;
    839    }
    840 
    841    else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT      ||
    842              ( do_read_var =
    843                  ( (FT_PaintFormat_Internal)apaint->format ==
    844                    FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT ) ) )
    845    {
    846      if ( !read_color_line( colr,
    847                             child_table_p,
    848                             &apaint->u.sweep_gradient.colorline,
    849                             do_read_var) )
    850        return 0;
    851 
    852      ENSURE_READ_BYTES( 8 );
    853 
    854      apaint->u.sweep_gradient.center.x =
    855          INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    856      apaint->u.sweep_gradient.center.y =
    857          INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    858 
    859      apaint->u.sweep_gradient.start_angle =
    860          F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
    861      apaint->u.sweep_gradient.end_angle =
    862          F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
    863 
    864 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    865      if ( do_read_var )
    866      {
    867        ENSURE_READ_BYTES( 4 );
    868        var_index_base = FT_NEXT_ULONG ( p );
    869 
    870        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
    871                                             item_deltas ) )
    872          return 0;
    873 
    874        // TODO: Handle overflow?
    875        apaint->u.sweep_gradient.center.x += INT_TO_FIXED( item_deltas[0] );
    876        apaint->u.sweep_gradient.center.y += INT_TO_FIXED( item_deltas[1] );
    877 
    878        apaint->u.sweep_gradient.start_angle +=
    879          F2DOT14_TO_FIXED( item_deltas[2] );
    880        apaint->u.sweep_gradient.end_angle +=
    881          F2DOT14_TO_FIXED( item_deltas[3] );
    882      }
    883 #endif
    884      apaint->format = FT_COLR_PAINTFORMAT_SWEEP_GRADIENT;
    885 
    886      return 1;
    887    }
    888 
    889    if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
    890    {
    891      ENSURE_READ_BYTES( 2 );
    892      apaint->u.glyph.paint.p                     = child_table_p;
    893      apaint->u.glyph.paint.insert_root_transform = 0;
    894      apaint->u.glyph.glyphID                     = FT_NEXT_USHORT( p );
    895 
    896      return 1;
    897    }
    898 
    899    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM ||
    900              (FT_PaintFormat_Internal)apaint->format ==
    901                FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM    )
    902    {
    903      apaint->u.transform.paint.p                     = child_table_p;
    904      apaint->u.transform.paint.insert_root_transform = 0;
    905 
    906      if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
    907         return 0;
    908 
    909      p = child_table_p;
    910 
    911      /*
    912       * The following matrix coefficients are encoded as
    913       * OpenType 16.16 fixed-point values.
    914       */
    915      ENSURE_READ_BYTES( 24 );
    916      apaint->u.transform.affine.xx = FT_NEXT_LONG( p );
    917      apaint->u.transform.affine.yx = FT_NEXT_LONG( p );
    918      apaint->u.transform.affine.xy = FT_NEXT_LONG( p );
    919      apaint->u.transform.affine.yy = FT_NEXT_LONG( p );
    920      apaint->u.transform.affine.dx = FT_NEXT_LONG( p );
    921      apaint->u.transform.affine.dy = FT_NEXT_LONG( p );
    922 
    923 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    924      if ( (FT_PaintFormat_Internal)apaint->format ==
    925             FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM )
    926      {
    927        ENSURE_READ_BYTES( 4 );
    928        var_index_base = FT_NEXT_ULONG( p );
    929 
    930        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6,
    931                                             item_deltas ) )
    932          return 0;
    933 
    934        apaint->u.transform.affine.xx += (FT_Fixed)item_deltas[0];
    935        apaint->u.transform.affine.yx += (FT_Fixed)item_deltas[1];
    936        apaint->u.transform.affine.xy += (FT_Fixed)item_deltas[2];
    937        apaint->u.transform.affine.yy += (FT_Fixed)item_deltas[3];
    938        apaint->u.transform.affine.dx += (FT_Fixed)item_deltas[4];
    939        apaint->u.transform.affine.dy += (FT_Fixed)item_deltas[5];
    940      }
    941 #endif
    942 
    943      apaint->format = FT_COLR_PAINTFORMAT_TRANSFORM;
    944 
    945      return 1;
    946    }
    947 
    948    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE ||
    949              (FT_PaintFormat_Internal)apaint->format ==
    950                FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE    )
    951    {
    952      apaint->u.translate.paint.p                     = child_table_p;
    953      apaint->u.translate.paint.insert_root_transform = 0;
    954 
    955      ENSURE_READ_BYTES( 4 );
    956      apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    957      apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
    958 
    959 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    960      if ( (FT_PaintFormat_Internal)apaint->format ==
    961             FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE )
    962      {
    963        ENSURE_READ_BYTES( 4 );
    964        var_index_base = FT_NEXT_ULONG( p );
    965 
    966        if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2,
    967                                             item_deltas ) )
    968          return 0;
    969 
    970        apaint->u.translate.dx += INT_TO_FIXED( item_deltas[0] );
    971        apaint->u.translate.dy += INT_TO_FIXED( item_deltas[1] );
    972      }
    973 #endif
    974 
    975      apaint->format = FT_COLR_PAINTFORMAT_TRANSLATE;
    976 
    977      return 1;
    978    }
    979 
    980    else if ( apaint->format >= FT_COLR_PAINTFORMAT_SCALE             &&
    981              (FT_PaintFormat_Internal)apaint->format <=
    982                FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
    983    {
    984      apaint->u.scale.paint.p                     = child_table_p;
    985      apaint->u.scale.paint.insert_root_transform = 0;
    986 
    987      /* All scale paints get at least one scale value. */
    988      ENSURE_READ_BYTES( 2 );
    989      apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
    990 
    991      /* Non-uniform ones read an extra y value. */
    992      if ( apaint->format == FT_COLR_PAINTFORMAT_SCALE     ||
    993           (FT_PaintFormat_Internal)apaint->format ==
    994             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE        ||
    995           (FT_PaintFormat_Internal)apaint->format ==
    996             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER     ||
    997           (FT_PaintFormat_Internal)apaint->format ==
    998             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER )
    999      {
   1000        ENSURE_READ_BYTES( 2 );
   1001        apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
   1002      }
   1003      else
   1004        apaint->u.scale.scale_y = apaint->u.scale.scale_x;
   1005 
   1006      /* Scale paints that have a center read center coordinates, */
   1007      /* otherwise the center is (0,0).                           */
   1008      if ( (FT_PaintFormat_Internal)apaint->format ==
   1009             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER             ||
   1010           (FT_PaintFormat_Internal)apaint->format ==
   1011             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER         ||
   1012           (FT_PaintFormat_Internal)apaint->format ==
   1013             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER     ||
   1014           (FT_PaintFormat_Internal)apaint->format ==
   1015             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
   1016      {
   1017        ENSURE_READ_BYTES( 4 );
   1018        apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
   1019        apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
   1020      }
   1021      else
   1022      {
   1023        apaint->u.scale.center_x = 0;
   1024        apaint->u.scale.center_y = 0;
   1025      }
   1026 
   1027      /* Base values set, now handle variations. */
   1028 
   1029 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   1030      if ( (FT_PaintFormat_Internal)apaint->format ==
   1031             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE                ||
   1032           (FT_PaintFormat_Internal)apaint->format ==
   1033             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER         ||
   1034           (FT_PaintFormat_Internal)apaint->format ==
   1035             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM        ||
   1036           (FT_PaintFormat_Internal)apaint->format ==
   1037             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
   1038      {
   1039        ENSURE_READ_BYTES( 4 );
   1040        var_index_base = FT_NEXT_ULONG( p );
   1041 
   1042        if ( (FT_PaintFormat_Internal)apaint->format ==
   1043               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE )
   1044        {
   1045          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2,
   1046                                               item_deltas ) )
   1047            return 0;
   1048 
   1049          apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] );
   1050          apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] );
   1051        }
   1052 
   1053        if ( (FT_PaintFormat_Internal)apaint->format ==
   1054               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER )
   1055        {
   1056          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
   1057                                               item_deltas ) )
   1058            return 0;
   1059 
   1060          apaint->u.scale.scale_x  += F2DOT14_TO_FIXED( item_deltas[0] );
   1061          apaint->u.scale.scale_y  += F2DOT14_TO_FIXED( item_deltas[1] );
   1062          apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[2] );
   1063          apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[3] );
   1064        }
   1065 
   1066        if ( (FT_PaintFormat_Internal)apaint->format ==
   1067               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM )
   1068        {
   1069          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1,
   1070                                               item_deltas ) )
   1071            return 0;
   1072 
   1073          apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] );
   1074          apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] );
   1075        }
   1076 
   1077        if ( (FT_PaintFormat_Internal)apaint->format ==
   1078               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER )
   1079        {
   1080          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 3,
   1081                                               item_deltas ) )
   1082            return 0;
   1083 
   1084          apaint->u.scale.scale_x  += F2DOT14_TO_FIXED( item_deltas[0] );
   1085          apaint->u.scale.scale_y  += F2DOT14_TO_FIXED( item_deltas[0] );
   1086          apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[1] );
   1087          apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[2] );
   1088        }
   1089      }
   1090 #endif
   1091 
   1092      /* FT 'COLR' v1 API output format always returns fully defined */
   1093      /* structs; we thus set the format to the public API value.    */
   1094      apaint->format = FT_COLR_PAINTFORMAT_SCALE;
   1095 
   1096      return 1;
   1097    }
   1098 
   1099    else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE     ||
   1100              (FT_PaintFormat_Internal)apaint->format ==
   1101                FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER     ||
   1102              (FT_PaintFormat_Internal)apaint->format ==
   1103                FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE        ||
   1104              (FT_PaintFormat_Internal)apaint->format ==
   1105                FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
   1106    {
   1107      apaint->u.rotate.paint.p                     = child_table_p;
   1108      apaint->u.rotate.paint.insert_root_transform = 0;
   1109 
   1110      ENSURE_READ_BYTES( 2 );
   1111      apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
   1112 
   1113      if ( (FT_PaintFormat_Internal)apaint->format ==
   1114             FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER     ||
   1115           (FT_PaintFormat_Internal)apaint->format ==
   1116             FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
   1117      {
   1118        ENSURE_READ_BYTES( 4 );
   1119        apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
   1120        apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
   1121      }
   1122      else
   1123      {
   1124        apaint->u.rotate.center_x = 0;
   1125        apaint->u.rotate.center_y = 0;
   1126      }
   1127 
   1128 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   1129      if ( (FT_PaintFormat_Internal)apaint->format ==
   1130             FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE        ||
   1131           (FT_PaintFormat_Internal)apaint->format ==
   1132             FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
   1133      {
   1134        FT_UInt  num_deltas = 0;
   1135 
   1136 
   1137        ENSURE_READ_BYTES( 4 );
   1138        var_index_base = FT_NEXT_ULONG( p );
   1139 
   1140        if ( (FT_PaintFormat_Internal)apaint->format ==
   1141               FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER )
   1142          num_deltas = 3;
   1143        if ( (FT_PaintFormat_Internal)apaint->format ==
   1144               FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE )
   1145          num_deltas = 1;
   1146 
   1147        if ( num_deltas > 0 )
   1148        {
   1149          if ( !get_deltas_for_var_index_base( face, colr, var_index_base,
   1150                                               num_deltas, item_deltas ) )
   1151            return 0;
   1152 
   1153          apaint->u.rotate.angle += F2DOT14_TO_FIXED( item_deltas[0] );
   1154 
   1155          if ( num_deltas == 3 )
   1156          {
   1157            apaint->u.rotate.center_x += INT_TO_FIXED( item_deltas[1] );
   1158            apaint->u.rotate.center_y += INT_TO_FIXED( item_deltas[2] );
   1159          }
   1160        }
   1161      }
   1162 #endif
   1163 
   1164      apaint->format = FT_COLR_PAINTFORMAT_ROTATE;
   1165 
   1166 
   1167      return 1;
   1168    }
   1169 
   1170    else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW     ||
   1171              (FT_PaintFormat_Internal)apaint->format ==
   1172                FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW        ||
   1173              (FT_PaintFormat_Internal)apaint->format ==
   1174                FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER     ||
   1175              (FT_PaintFormat_Internal)apaint->format ==
   1176                FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
   1177    {
   1178      apaint->u.skew.paint.p                     = child_table_p;
   1179      apaint->u.skew.paint.insert_root_transform = 0;
   1180 
   1181      ENSURE_READ_BYTES( 4 );
   1182      apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
   1183      apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
   1184 
   1185      if ( (FT_PaintFormat_Internal)apaint->format ==
   1186             FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER     ||
   1187           (FT_PaintFormat_Internal)apaint->format ==
   1188             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
   1189      {
   1190        ENSURE_READ_BYTES( 4 );
   1191        apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
   1192        apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
   1193      }
   1194      else
   1195      {
   1196        apaint->u.skew.center_x = 0;
   1197        apaint->u.skew.center_y = 0;
   1198      }
   1199 
   1200 
   1201 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   1202      if ( (FT_PaintFormat_Internal)apaint->format ==
   1203             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW        ||
   1204           (FT_PaintFormat_Internal)apaint->format ==
   1205             FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
   1206      {
   1207        ENSURE_READ_BYTES( 4 );
   1208        var_index_base = FT_NEXT_ULONG( p );
   1209 
   1210        if ( (FT_PaintFormat_Internal)apaint->format ==
   1211               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW )
   1212        {
   1213          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2,
   1214                                               item_deltas ) )
   1215            return 0;
   1216 
   1217          apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] );
   1218          apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] );
   1219        }
   1220 
   1221        if ( (FT_PaintFormat_Internal)apaint->format ==
   1222               FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER )
   1223        {
   1224          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
   1225                                               item_deltas ) )
   1226            return 0;
   1227 
   1228          apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] );
   1229          apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] );
   1230          apaint->u.skew.center_x     += INT_TO_FIXED( item_deltas[2] );
   1231          apaint->u.skew.center_y     += INT_TO_FIXED( item_deltas[3] );
   1232        }
   1233      }
   1234 #endif
   1235 
   1236      apaint->format = FT_COLR_PAINTFORMAT_SKEW;
   1237 
   1238      return 1;
   1239    }
   1240 
   1241    else if ( apaint->format == FT_COLR_PAINTFORMAT_COMPOSITE )
   1242    {
   1243      FT_UInt  composite_mode;
   1244 
   1245 
   1246      apaint->u.composite.source_paint.p                     = child_table_p;
   1247      apaint->u.composite.source_paint.insert_root_transform = 0;
   1248 
   1249      ENSURE_READ_BYTES( 1 );
   1250      composite_mode = FT_NEXT_BYTE( p );
   1251      if ( composite_mode >= FT_COLR_COMPOSITE_MAX )
   1252        return 0;
   1253 
   1254      apaint->u.composite.composite_mode = (FT_Composite_Mode)composite_mode;
   1255 
   1256      if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
   1257         return 0;
   1258 
   1259      apaint->u.composite.backdrop_paint.p =
   1260        child_table_p;
   1261      apaint->u.composite.backdrop_paint.insert_root_transform =
   1262        0;
   1263 
   1264      return 1;
   1265    }
   1266 
   1267    return 0;
   1268  }
   1269 
   1270 
   1271  static FT_Bool
   1272  find_base_glyph_v1_record( FT_Byte *           base_glyph_begin,
   1273                             FT_UInt             num_base_glyph,
   1274                             FT_UInt             glyph_id,
   1275                             BaseGlyphV1Record  *record )
   1276  {
   1277    FT_UInt  min = 0;
   1278    FT_UInt  max = num_base_glyph;
   1279 
   1280 
   1281    while ( min < max )
   1282    {
   1283      FT_UInt    mid = min + ( max - min ) / 2;
   1284      FT_UShort  gid;
   1285 
   1286      /*
   1287       * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
   1288       * skip `numBaseGlyphV1Records` by adding 4 to start binary search
   1289       * in the array of `BaseGlyphV1Record`.
   1290       */
   1291      FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
   1292 
   1293      gid = FT_NEXT_USHORT( p );
   1294 
   1295      if ( gid < glyph_id )
   1296        min = mid + 1;
   1297      else if (gid > glyph_id )
   1298        max = mid;
   1299      else
   1300      {
   1301        record->gid          = gid;
   1302        record->paint_offset = FT_NEXT_ULONG ( p );
   1303        return 1;
   1304      }
   1305    }
   1306 
   1307    return 0;
   1308  }
   1309 
   1310 
   1311  FT_LOCAL_DEF( FT_Bool )
   1312  tt_face_get_colr_glyph_paint( TT_Face                  face,
   1313                                FT_UInt                  base_glyph,
   1314                                FT_Color_Root_Transform  root_transform,
   1315                                FT_OpaquePaint*          opaque_paint )
   1316  {
   1317    Colr*              colr = (Colr*)face->colr;
   1318    BaseGlyphV1Record  base_glyph_v1_record;
   1319    FT_Byte*           p;
   1320 
   1321    if ( !colr || !colr->table )
   1322      return 0;
   1323 
   1324    if ( colr->version < 1 || !colr->num_base_glyphs_v1 ||
   1325         !colr->base_glyphs_v1 )
   1326      return 0;
   1327 
   1328    if ( opaque_paint->p )
   1329      return 0;
   1330 
   1331    if ( !find_base_glyph_v1_record( colr->base_glyphs_v1,
   1332                                     colr->num_base_glyphs_v1,
   1333                                     base_glyph,
   1334                                     &base_glyph_v1_record ) )
   1335      return 0;
   1336 
   1337    if ( !base_glyph_v1_record.paint_offset                   ||
   1338         base_glyph_v1_record.paint_offset > colr->table_size )
   1339      return 0;
   1340 
   1341    p = (FT_Byte*)( colr->base_glyphs_v1 +
   1342                    base_glyph_v1_record.paint_offset );
   1343    if ( p >= ( (FT_Byte*)colr->table + colr->table_size ) )
   1344      return 0;
   1345 
   1346    opaque_paint->p = p;
   1347 
   1348    if ( root_transform == FT_COLOR_INCLUDE_ROOT_TRANSFORM )
   1349      opaque_paint->insert_root_transform = 1;
   1350    else
   1351      opaque_paint->insert_root_transform = 0;
   1352 
   1353    return 1;
   1354  }
   1355 
   1356 
   1357  FT_LOCAL_DEF( FT_Bool )
   1358  tt_face_get_color_glyph_clipbox( TT_Face      face,
   1359                                   FT_UInt      base_glyph,
   1360                                   FT_ClipBox*  clip_box )
   1361  {
   1362    Colr*  colr;
   1363 
   1364    FT_Byte  *p, *p1, *clip_base, *limit;
   1365 
   1366    FT_Byte    clip_list_format;
   1367    FT_ULong   num_clip_boxes, i;
   1368    FT_UShort  gid_start, gid_end;
   1369    FT_UInt32  clip_box_offset;
   1370    FT_Byte    format;
   1371 
   1372    const FT_Byte  num_corners = 4;
   1373    FT_Vector      corners[4];
   1374    FT_Byte        j;
   1375    FT_BBox        font_clip_box;
   1376 
   1377 
   1378    colr = (Colr*)face->colr;
   1379    if ( !colr )
   1380      return 0;
   1381 
   1382    if ( !colr->clip_list )
   1383      return 0;
   1384 
   1385    p = colr->clip_list;
   1386 
   1387    /* Limit points to the first byte after the end of the color table.    */
   1388    /* Thus, in subsequent limit checks below we need to check whether the */
   1389    /* read pointer is strictly greater than a position offset by certain  */
   1390    /* field sizes to the left of that position.                           */
   1391    limit = (FT_Byte*)colr->table + colr->table_size;
   1392 
   1393    /* Check whether we can extract one `uint8` and one `uint32`. */
   1394    if ( p > limit - ( 1 + 4 ) )
   1395      return 0;
   1396 
   1397    clip_base        = p;
   1398    clip_list_format = FT_NEXT_BYTE ( p );
   1399 
   1400    /* Format byte used here to be able to upgrade ClipList for >16bit */
   1401    /* glyph ids; for now we can expect it to be 1.                    */
   1402    if ( !( clip_list_format == 1 ) )
   1403      return 0;
   1404 
   1405    num_clip_boxes = FT_NEXT_ULONG( p );
   1406 
   1407    /* Check whether we can extract two `uint16` and one `Offset24`, */
   1408    /* `num_clip_boxes` times.                                       */
   1409    if ( colr->table_size / ( 2 + 2 + 3 ) < num_clip_boxes ||
   1410         p > limit - ( 2 + 2 + 3 ) * num_clip_boxes        )
   1411      return 0;
   1412 
   1413    for ( i = 0; i < num_clip_boxes; ++i )
   1414    {
   1415      gid_start       = FT_NEXT_USHORT( p );
   1416      gid_end         = FT_NEXT_USHORT( p );
   1417      clip_box_offset = FT_NEXT_UOFF3( p );
   1418 
   1419      if ( base_glyph >= gid_start && base_glyph <= gid_end )
   1420      {
   1421        p1 = (FT_Byte*)( clip_base + clip_box_offset );
   1422 
   1423        /* Check whether we can extract one `uint8`. */
   1424        if ( p1 > limit - 1 )
   1425          return 0;
   1426 
   1427        format = FT_NEXT_BYTE( p1 );
   1428 
   1429        if ( format > 2 )
   1430          return 0;
   1431 
   1432        /* Check whether we can extract four `FWORD`. */
   1433        if ( p1 > limit - ( 2 + 2 + 2 + 2 ) )
   1434          return 0;
   1435 
   1436        /* `face->root.size->metrics.x_scale` and `y_scale` are factors   */
   1437        /* that scale a font unit value in integers to a 26.6 fixed value */
   1438        /* according to the requested size, see for example               */
   1439        /* `ft_recompute_scaled_metrics`.                                 */
   1440        font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
   1441                                        face->root.size->metrics.x_scale );
   1442        font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
   1443                                        face->root.size->metrics.y_scale );
   1444        font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
   1445                                        face->root.size->metrics.x_scale );
   1446        font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
   1447                                        face->root.size->metrics.y_scale );
   1448 
   1449 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   1450        if ( format == 2 )
   1451        {
   1452          FT_ULong         var_index_base = 0;
   1453          /* varIndexBase offset for clipbox is 3 at most. */
   1454          FT_ItemVarDelta  item_deltas[4] = { 0, 0, 0, 0 };
   1455 
   1456 
   1457          /* Check whether we can extract a 32-bit varIndexBase now. */
   1458          if ( p1 > limit - 4 )
   1459            return 0;
   1460 
   1461          var_index_base = FT_NEXT_ULONG( p1 );
   1462 
   1463          if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4,
   1464                                               item_deltas ) )
   1465            return 0;
   1466 
   1467          font_clip_box.xMin +=
   1468            FT_MulFix( item_deltas[0], face->root.size->metrics.x_scale );
   1469          font_clip_box.yMin +=
   1470            FT_MulFix( item_deltas[1], face->root.size->metrics.y_scale );
   1471          font_clip_box.xMax +=
   1472            FT_MulFix( item_deltas[2], face->root.size->metrics.x_scale );
   1473          font_clip_box.yMax +=
   1474            FT_MulFix( item_deltas[3], face->root.size->metrics.y_scale );
   1475        }
   1476 #endif
   1477 
   1478        /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */
   1479        /* them.  If we we would only transform two corner points and    */
   1480        /* span a rectangle based on those, the rectangle may become too */
   1481        /* small to cover the glyph.                                     */
   1482        corners[0].x = font_clip_box.xMin;
   1483        corners[1].x = font_clip_box.xMin;
   1484        corners[2].x = font_clip_box.xMax;
   1485        corners[3].x = font_clip_box.xMax;
   1486 
   1487        corners[0].y = font_clip_box.yMin;
   1488        corners[1].y = font_clip_box.yMax;
   1489        corners[2].y = font_clip_box.yMax;
   1490        corners[3].y = font_clip_box.yMin;
   1491 
   1492        for ( j = 0; j < num_corners; ++j )
   1493        {
   1494          if ( face->root.internal->transform_flags & 1 )
   1495            FT_Vector_Transform( &corners[j],
   1496                                 &face->root.internal->transform_matrix );
   1497 
   1498          if ( face->root.internal->transform_flags & 2 )
   1499          {
   1500            corners[j].x += face->root.internal->transform_delta.x;
   1501            corners[j].y += face->root.internal->transform_delta.y;
   1502          }
   1503        }
   1504 
   1505        clip_box->bottom_left  = corners[0];
   1506        clip_box->top_left     = corners[1];
   1507        clip_box->top_right    = corners[2];
   1508        clip_box->bottom_right = corners[3];
   1509 
   1510        return 1;
   1511      }
   1512    }
   1513 
   1514    return 0;
   1515  }
   1516 
   1517 
   1518  FT_LOCAL_DEF( FT_Bool )
   1519  tt_face_get_paint_layers( TT_Face            face,
   1520                            FT_LayerIterator*  iterator,
   1521                            FT_OpaquePaint*    opaque_paint )
   1522  {
   1523    FT_Byte*   p             = NULL;
   1524    FT_Byte*   p_first_layer = NULL;
   1525    FT_Byte*   p_paint       = NULL;
   1526    FT_UInt32  paint_offset;
   1527 
   1528    Colr*  colr;
   1529 
   1530 
   1531    if ( iterator->layer == iterator->num_layers )
   1532      return 0;
   1533 
   1534    colr = (Colr*)face->colr;
   1535    if ( !colr )
   1536      return 0;
   1537 
   1538    /*
   1539     * We have an iterator pointing at a paint offset as part of the
   1540     * `paintOffset` array in `LayerV1List`.
   1541     */
   1542    p = iterator->p;
   1543 
   1544    /*
   1545     * Do a cursor sanity check of the iterator.  Counting backwards from
   1546     * where it stands, we need to end up at a position after the beginning
   1547     * of the `LayerV1List` table and not after the end of the
   1548     * `LayerV1List`.
   1549     */
   1550    p_first_layer = p -
   1551                      iterator->layer * LAYER_V1_LIST_PAINT_OFFSET_SIZE -
   1552                      LAYER_V1_LIST_NUM_LAYERS_SIZE;
   1553    if ( p_first_layer < (FT_Byte*)colr->layers_v1 )
   1554      return 0;
   1555    if ( p_first_layer >= (FT_Byte*)(
   1556           colr->layers_v1 + LAYER_V1_LIST_NUM_LAYERS_SIZE +
   1557           colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) )
   1558      return 0;
   1559 
   1560    /*
   1561     * Before reading, ensure that `p` is within 'COLR' v1 and we can read a
   1562     * 4-byte ULONG.
   1563     */
   1564    if ( p < colr->layers_v1                              ||
   1565         p > (FT_Byte*)colr->table + colr->table_size - 4 )
   1566      return 0;
   1567 
   1568    paint_offset =
   1569      FT_NEXT_ULONG( p );
   1570    opaque_paint->insert_root_transform =
   1571      0;
   1572 
   1573    p_paint = (FT_Byte*)( colr->layers_v1 + paint_offset );
   1574 
   1575    if ( p_paint < colr->paints_start_v1                         ||
   1576         p_paint >= ( (FT_Byte*)colr->table + colr->table_size ) )
   1577      return 0;
   1578 
   1579    opaque_paint->p = p_paint;
   1580 
   1581    iterator->p = p;
   1582 
   1583    iterator->layer++;
   1584 
   1585    return 1;
   1586  }
   1587 
   1588 
   1589  FT_LOCAL_DEF( FT_Bool )
   1590  tt_face_get_colorline_stops( TT_Face                face,
   1591                               FT_ColorStop*          color_stop,
   1592                               FT_ColorStopIterator  *iterator )
   1593  {
   1594    Colr*  colr = (Colr*)face->colr;
   1595 
   1596    FT_Byte*  p;
   1597    FT_ULong  var_index_base;
   1598    FT_Byte*  last_entry_p = NULL;
   1599    FT_UInt   entry_size   = COLOR_STOP_SIZE;
   1600 
   1601 
   1602    if ( !colr || !colr->table || !iterator )
   1603      return 0;
   1604 
   1605    if ( iterator->current_color_stop >= iterator->num_color_stops )
   1606      return 0;
   1607 
   1608    if ( iterator->read_variable )
   1609      entry_size += VAR_IDX_BASE_SIZE;
   1610 
   1611    /* Calculate the start pointer for the last to-be-read (Var)ColorStop */
   1612    /* and check whether we can read a full (Var)ColorStop at that        */
   1613    /* position by comparing it to the position that is the size of one   */
   1614    /* (Var)ColorStop before the end of the 'COLR' table.                 */
   1615    last_entry_p =
   1616      iterator->p + ( iterator->num_color_stops - 1 -
   1617                      iterator->current_color_stop ) * entry_size;
   1618    if ( iterator->p < colr->paints_start_v1          ||
   1619         last_entry_p > (FT_Byte*)colr->table +
   1620                        colr->table_size - entry_size )
   1621      return 0;
   1622 
   1623    /* Iterator points at first `ColorStop` of `ColorLine`. */
   1624    p = iterator->p;
   1625 
   1626    color_stop->stop_offset = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
   1627 
   1628    color_stop->color.palette_index = FT_NEXT_USHORT( p );
   1629 
   1630    color_stop->color.alpha = FT_NEXT_SHORT( p );
   1631 
   1632    if ( iterator->read_variable )
   1633    {
   1634      /* Pointer p needs to be advanced independently of whether we intend */
   1635      /* to take variable deltas into account or not.  Otherwise iteration */
   1636      /* would fail due to wrong offsets.                                  */
   1637      var_index_base = FT_NEXT_ULONG( p );
   1638 
   1639 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
   1640      {
   1641        FT_Int  item_deltas[2];
   1642 
   1643 
   1644        if ( !get_deltas_for_var_index_base( face, colr,
   1645                                             var_index_base,
   1646                                             2,
   1647                                             item_deltas ) )
   1648          return 0;
   1649 
   1650        color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] );
   1651        color_stop->color.alpha += (FT_F2Dot14)item_deltas[1];
   1652      }
   1653 #else
   1654      FT_UNUSED( var_index_base );
   1655 #endif
   1656    }
   1657 
   1658    iterator->p = p;
   1659    iterator->current_color_stop++;
   1660 
   1661    return 1;
   1662  }
   1663 
   1664 
   1665  FT_LOCAL_DEF( FT_Bool )
   1666  tt_face_get_paint( TT_Face         face,
   1667                     FT_OpaquePaint  opaque_paint,
   1668                     FT_COLR_Paint*  paint )
   1669  {
   1670    Colr*           colr = (Colr*)face->colr;
   1671    FT_OpaquePaint  next_paint;
   1672    FT_Matrix       ft_root_scale;
   1673 
   1674    if ( !colr || !colr->base_glyphs_v1 || !colr->table )
   1675      return 0;
   1676 
   1677    if ( opaque_paint.insert_root_transform )
   1678    {
   1679      /* 'COLR' v1 glyph information is returned in unscaled coordinates,
   1680       * i.e., `FT_Size` is not applied or multiplied into the values.  When
   1681       * client applications draw color glyphs, they can request to include
   1682       * a top-level transform, which includes the active `x_scale` and
   1683       * `y_scale` information for scaling the glyph, as well the additional
   1684       * transform and translate configured through `FT_Set_Transform`.
   1685       * This allows client applications to apply this top-level transform
   1686       * to the graphics context first and only once, then have gradient and
   1687       * contour scaling applied correctly when performing the additional
   1688       * drawing operations for subsequenct paints.  Prepare this initial
   1689       * transform here.
   1690       */
   1691      paint->format = FT_COLR_PAINTFORMAT_TRANSFORM;
   1692 
   1693      next_paint.p                     = opaque_paint.p;
   1694      next_paint.insert_root_transform = 0;
   1695      paint->u.transform.paint         = next_paint;
   1696 
   1697      /* `x_scale` and `y_scale` are in 26.6 format, representing the scale
   1698       * factor to get from font units to requested size.  However, expected
   1699       * return values are in 16.16, so we shift accordingly with rounding.
   1700       */
   1701      ft_root_scale.xx = ( face->root.size->metrics.x_scale + 32 ) >> 6;
   1702      ft_root_scale.xy = 0;
   1703      ft_root_scale.yx = 0;
   1704      ft_root_scale.yy = ( face->root.size->metrics.y_scale + 32 ) >> 6;
   1705 
   1706      if ( face->root.internal->transform_flags & 1 )
   1707        FT_Matrix_Multiply( &face->root.internal->transform_matrix,
   1708                            &ft_root_scale );
   1709 
   1710      paint->u.transform.affine.xx = ft_root_scale.xx;
   1711      paint->u.transform.affine.xy = ft_root_scale.xy;
   1712      paint->u.transform.affine.yx = ft_root_scale.yx;
   1713      paint->u.transform.affine.yy = ft_root_scale.yy;
   1714 
   1715      /* The translation is specified in 26.6 format and, according to the
   1716       * documentation of `FT_Set_Translate`, is performed on the character
   1717       * size given in the last call to `FT_Set_Char_Size`.  The
   1718       * 'PaintTransform' paint table's `FT_Affine23` format expects
   1719       * values in 16.16 format, thus we need to shift by 10 bits.
   1720       */
   1721      if ( face->root.internal->transform_flags & 2 )
   1722      {
   1723        paint->u.transform.affine.dx =
   1724          face->root.internal->transform_delta.x * ( 1 << 10 );
   1725        paint->u.transform.affine.dy =
   1726          face->root.internal->transform_delta.y * ( 1 << 10 );
   1727      }
   1728      else
   1729      {
   1730        paint->u.transform.affine.dx = 0;
   1731        paint->u.transform.affine.dy = 0;
   1732      }
   1733 
   1734      return 1;
   1735    }
   1736 
   1737    return read_paint( face, colr, opaque_paint.p, paint );
   1738  }
   1739 
   1740 
   1741  FT_LOCAL_DEF( FT_Error )
   1742  tt_face_colr_blend_layer( TT_Face       face,
   1743                            FT_UInt       color_index,
   1744                            FT_GlyphSlot  dstSlot,
   1745                            FT_GlyphSlot  srcSlot )
   1746  {
   1747    FT_Error  error;
   1748 
   1749    FT_UInt  x, y;
   1750    FT_Byte  b, g, r, alpha;
   1751 
   1752    FT_ULong  size;
   1753    FT_Byte*  src;
   1754    FT_Byte*  dst;
   1755 
   1756 
   1757    if ( !dstSlot->bitmap.buffer )
   1758    {
   1759      /* Initialize destination of color bitmap */
   1760      /* with the size of first component.      */
   1761      dstSlot->bitmap_left = srcSlot->bitmap_left;
   1762      dstSlot->bitmap_top  = srcSlot->bitmap_top;
   1763 
   1764      dstSlot->bitmap.width      = srcSlot->bitmap.width;
   1765      dstSlot->bitmap.rows       = srcSlot->bitmap.rows;
   1766      dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
   1767      dstSlot->bitmap.pitch      = (int)dstSlot->bitmap.width * 4;
   1768      dstSlot->bitmap.num_grays  = 256;
   1769 
   1770      size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch;
   1771 
   1772      error = ft_glyphslot_alloc_bitmap( dstSlot, size );
   1773      if ( error )
   1774        return error;
   1775 
   1776      FT_MEM_ZERO( dstSlot->bitmap.buffer, size );
   1777    }
   1778    else
   1779    {
   1780      /* Resize destination if needed such that new component fits. */
   1781      FT_Int  x_min, x_max, y_min, y_max;
   1782 
   1783 
   1784      x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left );
   1785      x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width,
   1786                      srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width );
   1787 
   1788      y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows,
   1789                      srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows );
   1790      y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top );
   1791 
   1792      if ( x_min != dstSlot->bitmap_left                                 ||
   1793           x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width ||
   1794           y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows   ||
   1795           y_max != dstSlot->bitmap_top                                  )
   1796      {
   1797        FT_Memory  memory = face->root.memory;
   1798 
   1799        FT_UInt  width = (FT_UInt)( x_max - x_min );
   1800        FT_UInt  rows  = (FT_UInt)( y_max - y_min );
   1801        FT_UInt  pitch = width * 4;
   1802 
   1803        FT_Byte*  buf = NULL;
   1804        FT_Byte*  p;
   1805        FT_Byte*  q;
   1806 
   1807 
   1808        size  = rows * pitch;
   1809        if ( FT_ALLOC( buf, size ) )
   1810          return error;
   1811 
   1812        p = dstSlot->bitmap.buffer;
   1813        q = buf +
   1814            (int)pitch * ( y_max - dstSlot->bitmap_top ) +
   1815            4 * ( dstSlot->bitmap_left - x_min );
   1816 
   1817        for ( y = 0; y < dstSlot->bitmap.rows; y++ )
   1818        {
   1819          FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 );
   1820 
   1821          p += dstSlot->bitmap.pitch;
   1822          q += pitch;
   1823        }
   1824 
   1825        ft_glyphslot_set_bitmap( dstSlot, buf );
   1826 
   1827        dstSlot->bitmap_top  = y_max;
   1828        dstSlot->bitmap_left = x_min;
   1829 
   1830        dstSlot->bitmap.width = width;
   1831        dstSlot->bitmap.rows  = rows;
   1832        dstSlot->bitmap.pitch = (int)pitch;
   1833 
   1834        dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP;
   1835        dstSlot->format           = FT_GLYPH_FORMAT_BITMAP;
   1836      }
   1837    }
   1838 
   1839    if ( color_index == 0xFFFF )
   1840    {
   1841      if ( face->have_foreground_color )
   1842      {
   1843        b     = face->foreground_color.blue;
   1844        g     = face->foreground_color.green;
   1845        r     = face->foreground_color.red;
   1846        alpha = face->foreground_color.alpha;
   1847      }
   1848      else
   1849      {
   1850        if ( face->palette_data.palette_flags                          &&
   1851             ( face->palette_data.palette_flags[face->palette_index] &
   1852                 FT_PALETTE_FOR_DARK_BACKGROUND                      ) )
   1853        {
   1854          /* white opaque */
   1855          b     = 0xFF;
   1856          g     = 0xFF;
   1857          r     = 0xFF;
   1858          alpha = 0xFF;
   1859        }
   1860        else
   1861        {
   1862          /* black opaque */
   1863          b     = 0x00;
   1864          g     = 0x00;
   1865          r     = 0x00;
   1866          alpha = 0xFF;
   1867        }
   1868      }
   1869    }
   1870    else
   1871    {
   1872      b     = face->palette[color_index].blue;
   1873      g     = face->palette[color_index].green;
   1874      r     = face->palette[color_index].red;
   1875      alpha = face->palette[color_index].alpha;
   1876    }
   1877 
   1878    /* XXX Convert if srcSlot.bitmap is not grey? */
   1879    src = srcSlot->bitmap.buffer;
   1880    dst = dstSlot->bitmap.buffer +
   1881          dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) +
   1882          4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left );
   1883 
   1884    for ( y = 0; y < srcSlot->bitmap.rows; y++ )
   1885    {
   1886      for ( x = 0; x < srcSlot->bitmap.width; x++ )
   1887      {
   1888        int  aa = src[x];
   1889        int  fa = alpha * aa / 255;
   1890 
   1891        int  fb = b * fa / 255;
   1892        int  fg = g * fa / 255;
   1893        int  fr = r * fa / 255;
   1894 
   1895        int  ba2 = 255 - fa;
   1896 
   1897        int  bb = dst[4 * x + 0];
   1898        int  bg = dst[4 * x + 1];
   1899        int  br = dst[4 * x + 2];
   1900        int  ba = dst[4 * x + 3];
   1901 
   1902 
   1903        dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb );
   1904        dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg );
   1905        dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr );
   1906        dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa );
   1907      }
   1908 
   1909      src += srcSlot->bitmap.pitch;
   1910      dst += dstSlot->bitmap.pitch;
   1911    }
   1912 
   1913    return FT_Err_Ok;
   1914  }
   1915 
   1916 #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
   1917 
   1918  /* ANSI C doesn't like empty source files */
   1919  typedef int  tt_colr_dummy_;
   1920 
   1921 #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
   1922 
   1923 /* EOF */