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