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