• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 )
tt_face_load_colr(TT_Face face,FT_Stream stream)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 )
tt_face_free_colr(TT_Face face)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
find_base_glyph_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphRecord * record)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 )
tt_face_get_colr_layer(TT_Face face,FT_UInt base_glyph,FT_UInt * aglyph_index,FT_UInt * acolor_index,FT_LayerIterator * iterator)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
read_color_line(Colr * colr,FT_Byte * color_line_p,FT_ColorLine * colorline,FT_Bool read_variable)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
get_child_table_pointer(Colr * colr,FT_Byte * paint_base,FT_Byte ** p,FT_Byte ** child_table_pointer)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
get_deltas_for_var_index_base(TT_Face face,Colr * colr,FT_ULong var_index_base,FT_UInt num_deltas,FT_ItemVarDelta * deltas)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
read_paint(TT_Face face,Colr * colr,FT_Byte * p,FT_COLR_Paint * apaint)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
find_base_glyph_v1_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphV1Record * record)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 )
tt_face_get_colr_glyph_paint(TT_Face face,FT_UInt base_glyph,FT_Color_Root_Transform root_transform,FT_OpaquePaint * opaque_paint)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 )
tt_face_get_color_glyph_clipbox(TT_Face face,FT_UInt base_glyph,FT_ClipBox * clip_box)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 )
tt_face_get_paint_layers(TT_Face face,FT_LayerIterator * iterator,FT_OpaquePaint * opaque_paint)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 )
tt_face_get_colorline_stops(TT_Face face,FT_ColorStop * color_stop,FT_ColorStopIterator * iterator)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 )
tt_face_get_paint(TT_Face face,FT_OpaquePaint opaque_paint,FT_COLR_Paint * paint)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 )
tt_face_colr_blend_layer(TT_Face face,FT_UInt color_index,FT_GlyphSlot dstSlot,FT_GlyphSlot srcSlot)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 */
1922