• 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-2021 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 
38 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
39 
40 #include "ttcolr.h"
41 
42 
43   /* NOTE: These are the table sizes calculated through the specs. */
44 #define BASE_GLYPH_SIZE                   6U
45 #define BASE_GLYPH_PAINT_RECORD_SIZE      6U
46 #define LAYER_V1_LIST_PAINT_OFFSET_SIZE   4U
47 #define LAYER_V1_LIST_NUM_LAYERS_SIZE     4U
48 #define COLOR_STOP_SIZE                   6U
49 #define LAYER_SIZE                        4U
50 #define COLR_HEADER_SIZE                 14U
51 
52 #define ENSURE_READ_BYTES( byte_size )                             \
53   if ( p < colr->paints_start_v1                                || \
54        p > (FT_Byte*)colr->table + colr->table_size - byte_size )  \
55     return 0;
56 
57 
58   typedef enum  FT_PaintFormat_Internal_
59   {
60     FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         = 18,
61     FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM        = 20,
62     FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22,
63     FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER        = 26,
64     FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER          = 30
65 
66   } FT_PaintFormat_Internal;
67 
68 
69   typedef struct  BaseGlyphRecord_
70   {
71     FT_UShort  gid;
72     FT_UShort  first_layer_index;
73     FT_UShort  num_layers;
74 
75   } BaseGlyphRecord;
76 
77 
78   typedef struct  BaseGlyphV1Record_
79   {
80     FT_UShort  gid;
81     /* Offset from start of BaseGlyphV1List, i.e., from base_glyphs_v1. */
82     FT_ULong   paint_offset;
83 
84   } BaseGlyphV1Record;
85 
86 
87   typedef struct  Colr_
88   {
89     FT_UShort  version;
90     FT_UShort  num_base_glyphs;
91     FT_UShort  num_layers;
92 
93     FT_Byte*  base_glyphs;
94     FT_Byte*  layers;
95 
96     FT_ULong  num_base_glyphs_v1;
97     /* Points at beginning of BaseGlyphV1List. */
98     FT_Byte*  base_glyphs_v1;
99 
100     FT_ULong  num_layers_v1;
101     FT_Byte*  layers_v1;
102 
103     FT_Byte*  clip_list;
104 
105     /*
106      * Paint tables start at the minimum of the end of the LayerList and the
107      * end of the BaseGlyphList.  Record this location in a field here for
108      * safety checks when accessing paint tables.
109      */
110     FT_Byte*  paints_start_v1;
111 
112     /* The memory that backs up the `COLR' table. */
113     void*     table;
114     FT_ULong  table_size;
115 
116   } Colr;
117 
118 
119   /**************************************************************************
120    *
121    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
122    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
123    * messages during execution.
124    */
125 #undef  FT_COMPONENT
126 #define FT_COMPONENT  ttcolr
127 
128 
129   FT_LOCAL_DEF( FT_Error )
tt_face_load_colr(TT_Face face,FT_Stream stream)130   tt_face_load_colr( TT_Face    face,
131                      FT_Stream  stream )
132   {
133     FT_Error   error;
134     FT_Memory  memory = face->root.memory;
135 
136     FT_Byte*  table = NULL;
137     FT_Byte*  p     = NULL;
138     /* Needed for reading array lengths in referenced tables. */
139     FT_Byte*  p1    = NULL;
140 
141     Colr*  colr = NULL;
142 
143     FT_ULong  base_glyph_offset, layer_offset;
144     FT_ULong  base_glyphs_offset_v1, num_base_glyphs_v1;
145     FT_ULong  layer_offset_v1, num_layers_v1, clip_list_offset;
146     FT_ULong  table_size;
147 
148 
149     /* `COLR' always needs `CPAL' */
150     if ( !face->cpal )
151       return FT_THROW( Invalid_File_Format );
152 
153     error = face->goto_table( face, TTAG_COLR, stream, &table_size );
154     if ( error )
155       goto NoColr;
156 
157     if ( table_size < COLR_HEADER_SIZE )
158       goto InvalidTable;
159 
160     if ( FT_FRAME_EXTRACT( table_size, table ) )
161       goto NoColr;
162 
163     p = table;
164 
165     if ( FT_NEW( colr ) )
166       goto NoColr;
167 
168     colr->version = FT_NEXT_USHORT( p );
169     if ( colr->version != 0 && colr->version != 1 )
170       goto InvalidTable;
171 
172     colr->num_base_glyphs = FT_NEXT_USHORT( p );
173     base_glyph_offset     = FT_NEXT_ULONG( p );
174 
175     if ( base_glyph_offset >= table_size )
176       goto InvalidTable;
177     if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
178            table_size - base_glyph_offset )
179       goto InvalidTable;
180 
181     layer_offset     = FT_NEXT_ULONG( p );
182     colr->num_layers = FT_NEXT_USHORT( p );
183 
184     if ( layer_offset >= table_size )
185       goto InvalidTable;
186     if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
187       goto InvalidTable;
188 
189     if ( colr->version == 1 )
190     {
191       base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
192 
193       if ( base_glyphs_offset_v1 >= table_size )
194         goto InvalidTable;
195 
196       p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
197       num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
198 
199       if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE >
200              table_size - base_glyphs_offset_v1 )
201         goto InvalidTable;
202 
203       colr->num_base_glyphs_v1 = num_base_glyphs_v1;
204       colr->base_glyphs_v1     = p1;
205 
206       layer_offset_v1 = FT_NEXT_ULONG( p );
207 
208       if ( layer_offset_v1 >= table_size )
209         goto InvalidTable;
210 
211       if ( layer_offset_v1 )
212       {
213         p1            = (FT_Byte*)( table + layer_offset_v1 );
214         num_layers_v1 = FT_PEEK_ULONG( p1 );
215 
216         if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
217                table_size - layer_offset_v1 )
218           goto InvalidTable;
219 
220         colr->num_layers_v1 = num_layers_v1;
221         colr->layers_v1     = p1;
222 
223         colr->paints_start_v1 =
224             FT_MIN( colr->base_glyphs_v1 +
225                     colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE,
226                     colr->layers_v1 +
227                     colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE );
228       }
229       else
230       {
231         colr->num_layers_v1   = 0;
232         colr->layers_v1       = 0;
233         colr->paints_start_v1 =
234           colr->base_glyphs_v1 +
235           colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE;
236       }
237 
238       clip_list_offset = FT_NEXT_ULONG( p );
239 
240       if ( clip_list_offset >= table_size )
241         goto InvalidTable;
242 
243       if ( clip_list_offset )
244         colr->clip_list = (FT_Byte*)( table + clip_list_offset );
245       else
246         colr->clip_list = 0;
247     }
248 
249     colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );
250     colr->layers      = (FT_Byte*)( table + layer_offset      );
251     colr->table       = table;
252     colr->table_size  = table_size;
253 
254     face->colr = colr;
255 
256     return FT_Err_Ok;
257 
258   InvalidTable:
259     error = FT_THROW( Invalid_Table );
260 
261   NoColr:
262     FT_FRAME_RELEASE( table );
263     FT_FREE( colr );
264 
265     return error;
266   }
267 
268 
269   FT_LOCAL_DEF( void )
tt_face_free_colr(TT_Face face)270   tt_face_free_colr( TT_Face  face )
271   {
272     FT_Stream  stream = face->root.stream;
273     FT_Memory  memory = face->root.memory;
274 
275     Colr*  colr = (Colr*)face->colr;
276 
277 
278     if ( colr )
279     {
280       FT_FRAME_RELEASE( colr->table );
281       FT_FREE( colr );
282     }
283   }
284 
285 
286   static FT_Bool
find_base_glyph_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphRecord * record)287   find_base_glyph_record( FT_Byte*          base_glyph_begin,
288                           FT_UInt           num_base_glyph,
289                           FT_UInt           glyph_id,
290                           BaseGlyphRecord*  record )
291   {
292     FT_UInt  min = 0;
293     FT_UInt  max = num_base_glyph;
294 
295 
296     while ( min < max )
297     {
298       FT_UInt   mid = min + ( max - min ) / 2;
299       FT_Byte*  p   = base_glyph_begin + mid * BASE_GLYPH_SIZE;
300 
301       FT_UShort  gid = FT_NEXT_USHORT( p );
302 
303 
304       if ( gid < glyph_id )
305         min = mid + 1;
306       else if (gid > glyph_id )
307         max = mid;
308       else
309       {
310         record->gid               = gid;
311         record->first_layer_index = FT_NEXT_USHORT( p );
312         record->num_layers        = FT_NEXT_USHORT( p );
313 
314         return 1;
315       }
316     }
317 
318     return 0;
319   }
320 
321 
322   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)323   tt_face_get_colr_layer( TT_Face            face,
324                           FT_UInt            base_glyph,
325                           FT_UInt           *aglyph_index,
326                           FT_UInt           *acolor_index,
327                           FT_LayerIterator*  iterator )
328   {
329     Colr*            colr = (Colr*)face->colr;
330     BaseGlyphRecord  glyph_record;
331 
332 
333     if ( !colr )
334       return 0;
335 
336     if ( !iterator->p )
337     {
338       FT_ULong  offset;
339 
340 
341       /* first call to function */
342       iterator->layer = 0;
343 
344       if ( !find_base_glyph_record( colr->base_glyphs,
345                                     colr->num_base_glyphs,
346                                     base_glyph,
347                                     &glyph_record ) )
348         return 0;
349 
350       if ( glyph_record.num_layers )
351         iterator->num_layers = glyph_record.num_layers;
352       else
353         return 0;
354 
355       offset = LAYER_SIZE * glyph_record.first_layer_index;
356       if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size )
357         return 0;
358 
359       iterator->p = colr->layers + offset;
360     }
361 
362     if ( iterator->layer >= iterator->num_layers )
363       return 0;
364 
365     *aglyph_index = FT_NEXT_USHORT( iterator->p );
366     *acolor_index = FT_NEXT_USHORT( iterator->p );
367 
368     if ( *aglyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs )   ||
369          ( *acolor_index != 0xFFFF                                 &&
370            *acolor_index >= face->palette_data.num_palette_entries ) )
371       return 0;
372 
373     iterator->layer++;
374 
375     return 1;
376   }
377 
378 
379   static FT_Bool
read_color_line(Colr * colr,FT_Byte * color_line_p,FT_ColorLine * colorline)380   read_color_line( Colr*          colr,
381                    FT_Byte*       color_line_p,
382                    FT_ColorLine*  colorline)
383   {
384     FT_Byte*        p = color_line_p;
385     FT_PaintExtend  paint_extend;
386 
387 
388     ENSURE_READ_BYTES( 3 );
389 
390     paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p );
391     if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT )
392       return 0;
393 
394     colorline->extend = paint_extend;
395 
396     colorline->color_stop_iterator.num_color_stops    = FT_NEXT_USHORT( p );
397     colorline->color_stop_iterator.p                  = p;
398     colorline->color_stop_iterator.current_color_stop = 0;
399 
400     return 1;
401   }
402 
403 
404   /*
405    * Read a paint offset for `FT_Paint*` objects that have them and check
406    * whether it is within reasonable limits within the font and the COLR
407    * table.
408    *
409    * Return 1 on success, 0 on failure.
410    */
411   static FT_Bool
get_child_table_pointer(Colr * colr,FT_Byte * paint_base,FT_Byte ** p,FT_Byte ** child_table_pointer)412   get_child_table_pointer ( Colr*      colr,
413                             FT_Byte*   paint_base,
414                             FT_Byte**  p,
415                             FT_Byte**  child_table_pointer )
416   {
417     FT_UInt32  paint_offset;
418     FT_Byte*   child_table_p;
419 
420 
421     if ( !child_table_pointer )
422       return 0;
423 
424     paint_offset = FT_NEXT_UOFF3( *p );
425     if ( !paint_offset )
426       return 0;
427 
428     child_table_p = (FT_Byte*)( paint_base + paint_offset );
429 
430     if ( child_table_p < colr->paints_start_v1                         ||
431          child_table_p >= ( (FT_Byte*)colr->table + colr->table_size ) )
432       return 0;
433 
434     *child_table_pointer = child_table_p;
435     return 1;
436   }
437 
438 
439   static FT_Bool
read_paint(Colr * colr,FT_Byte * p,FT_COLR_Paint * apaint)440   read_paint( Colr*           colr,
441               FT_Byte*        p,
442               FT_COLR_Paint*  apaint )
443   {
444     FT_Byte*  paint_base     = p;
445     FT_Byte*  child_table_p  = NULL;
446 
447 
448     if ( !p || !colr || !colr->table )
449       return 0;
450 
451     if ( p < colr->paints_start_v1                         ||
452          p >= ( (FT_Byte*)colr->table + colr->table_size ) )
453       return 0;
454 
455     apaint->format = (FT_PaintFormat)FT_NEXT_BYTE( p );
456 
457     if ( apaint->format >= FT_COLR_PAINT_FORMAT_MAX )
458       return 0;
459 
460     if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_LAYERS )
461     {
462       /* Initialize layer iterator/ */
463       FT_Byte    num_layers;
464       FT_UInt32  first_layer_index;
465 
466 
467       num_layers = FT_NEXT_BYTE( p );
468       if ( num_layers > colr->num_layers_v1 )
469         return 0;
470 
471       first_layer_index = FT_NEXT_ULONG( p );
472       if ( first_layer_index + num_layers > colr->num_layers_v1 )
473         return 0;
474 
475       apaint->u.colr_layers.layer_iterator.num_layers = num_layers;
476       apaint->u.colr_layers.layer_iterator.layer      = 0;
477       /* TODO: Check whether pointer is outside colr? */
478       apaint->u.colr_layers.layer_iterator.p =
479         colr->layers_v1 +
480         LAYER_V1_LIST_NUM_LAYERS_SIZE +
481         LAYER_V1_LIST_PAINT_OFFSET_SIZE * first_layer_index;
482 
483       return 1;
484     }
485 
486     else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID )
487     {
488       ENSURE_READ_BYTES( 4 );
489       apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p );
490       apaint->u.solid.color.alpha         = FT_NEXT_SHORT( p );
491 
492       return 1;
493     }
494 
495     else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
496     {
497       ENSURE_READ_BYTES(2);
498       apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
499 
500       return 1;
501     }
502 
503     /*
504      * Grouped below here are all paint formats that have an offset to a
505      * child paint table as the first entry (for example, a color line or a
506      * child paint table).  Retrieve that and determine whether that paint
507      * offset is valid first.
508      */
509 
510     if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
511       return 0;
512 
513     if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
514     {
515       if ( !read_color_line( colr,
516                              child_table_p,
517                              &apaint->u.linear_gradient.colorline) )
518         return 0;
519 
520       /*
521        * In order to support variations expose these as FT_Fixed 16.16 values so
522        * that we can support fractional values after interpolation.
523        */
524       ENSURE_READ_BYTES( 12 );
525       apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
526       apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
527       apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
528       apaint->u.linear_gradient.p1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
529       apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
530       apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
531 
532       return 1;
533     }
534 
535     else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
536     {
537       FT_Pos  tmp;
538 
539 
540       if ( !read_color_line( colr,
541                              child_table_p,
542                              &apaint->u.radial_gradient.colorline) )
543         return 0;
544 
545       /* In the OpenType specification, `r0` and `r1` are defined as   */
546       /* `UFWORD`.  Since FreeType doesn't have a corresponding 16.16  */
547       /* format we convert to `FWORD` and replace negative values with */
548       /* (32bit) `FT_INT_MAX`.                                         */
549 
550       ENSURE_READ_BYTES( 12 );
551 
552       apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
553       apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
554 
555       apaint->u.radial_gradient.r0 = FT_NEXT_USHORT( p ) << 16;
556 
557       apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
558       apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
559 
560       apaint->u.radial_gradient.r1 = FT_NEXT_USHORT( p ) << 16;
561 
562       return 1;
563     }
564 
565     else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT )
566     {
567       if ( !read_color_line( colr,
568                              child_table_p,
569                              &apaint->u.sweep_gradient.colorline) )
570         return 0;
571 
572       ENSURE_READ_BYTES( 8 );
573 
574       apaint->u.sweep_gradient.center.x =
575           INT_TO_FIXED( FT_NEXT_SHORT( p ) );
576       apaint->u.sweep_gradient.center.y =
577           INT_TO_FIXED( FT_NEXT_SHORT( p ) );
578 
579       apaint->u.sweep_gradient.start_angle =
580           F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
581       apaint->u.sweep_gradient.end_angle =
582           F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
583 
584       return 1;
585     }
586 
587     if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
588     {
589       ENSURE_READ_BYTES( 2 );
590       apaint->u.glyph.paint.p                     = child_table_p;
591       apaint->u.glyph.paint.insert_root_transform = 0;
592       apaint->u.glyph.glyphID                     = FT_NEXT_USHORT( p );
593 
594       return 1;
595     }
596 
597     else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM )
598     {
599       apaint->u.transform.paint.p                     = child_table_p;
600       apaint->u.transform.paint.insert_root_transform = 0;
601 
602       if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
603          return 0;
604 
605       p = child_table_p;
606 
607       /*
608        * The following matrix coefficients are encoded as
609        * OpenType 16.16 fixed-point values.
610        */
611       ENSURE_READ_BYTES( 24 );
612       apaint->u.transform.affine.xx = FT_NEXT_LONG( p );
613       apaint->u.transform.affine.yx = FT_NEXT_LONG( p );
614       apaint->u.transform.affine.xy = FT_NEXT_LONG( p );
615       apaint->u.transform.affine.yy = FT_NEXT_LONG( p );
616       apaint->u.transform.affine.dx = FT_NEXT_LONG( p );
617       apaint->u.transform.affine.dy = FT_NEXT_LONG( p );
618 
619       return 1;
620     }
621 
622     else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE )
623     {
624       apaint->u.translate.paint.p                     = child_table_p;
625       apaint->u.translate.paint.insert_root_transform = 0;
626 
627       ENSURE_READ_BYTES( 4 );
628       apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
629       apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
630 
631       return 1;
632     }
633 
634     else if ( apaint->format ==
635                 FT_COLR_PAINTFORMAT_SCALE                         ||
636               (FT_PaintFormat_Internal)apaint->format ==
637                 FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         ||
638               (FT_PaintFormat_Internal)apaint->format ==
639                 FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM        ||
640               (FT_PaintFormat_Internal)apaint->format ==
641                 FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
642     {
643       apaint->u.scale.paint.p                     = child_table_p;
644       apaint->u.scale.paint.insert_root_transform = 0;
645 
646       /* All scale paints get at least one scale value. */
647       ENSURE_READ_BYTES( 2 );
648       apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
649 
650       /* Non-uniform ones read an extra y value. */
651       if ( apaint->format ==
652              FT_COLR_PAINTFORMAT_SCALE                 ||
653            (FT_PaintFormat_Internal)apaint->format ==
654              FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER )
655       {
656         ENSURE_READ_BYTES( 2 );
657         apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
658       }
659       else
660         apaint->u.scale.scale_y = apaint->u.scale.scale_x;
661 
662       /* Scale paints that have a center read center coordinates, */
663       /* otherwise the center is (0,0).                           */
664       if ( (FT_PaintFormat_Internal)apaint->format ==
665              FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         ||
666            (FT_PaintFormat_Internal)apaint->format ==
667              FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
668       {
669         ENSURE_READ_BYTES( 4 );
670         apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
671         apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
672       }
673       else
674       {
675         apaint->u.scale.center_x = 0;
676         apaint->u.scale.center_y = 0;
677       }
678 
679       /* FT 'COLR' v1 API output format always returns fully defined */
680       /* structs; we thus set the format to the public API value.    */
681       apaint->format = FT_COLR_PAINTFORMAT_SCALE;
682 
683       return 1;
684     }
685 
686     else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE ||
687               (FT_PaintFormat_Internal)apaint->format ==
688                 FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
689     {
690       apaint->u.rotate.paint.p                     = child_table_p;
691       apaint->u.rotate.paint.insert_root_transform = 0;
692 
693       ENSURE_READ_BYTES( 2 );
694       apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
695 
696       if ( (FT_PaintFormat_Internal)apaint->format ==
697            FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
698       {
699         ENSURE_READ_BYTES( 4 );
700         apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
701         apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
702       }
703       else
704       {
705         apaint->u.rotate.center_x = 0;
706         apaint->u.rotate.center_y = 0;
707       }
708 
709       apaint->format = FT_COLR_PAINTFORMAT_ROTATE;
710 
711       return 1;
712     }
713 
714     else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW ||
715               (FT_PaintFormat_Internal)apaint->format ==
716                 FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
717     {
718       apaint->u.skew.paint.p                     = child_table_p;
719       apaint->u.skew.paint.insert_root_transform = 0;
720 
721       ENSURE_READ_BYTES( 4 );
722       apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
723       apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
724 
725       if ( (FT_PaintFormat_Internal)apaint->format ==
726            FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
727       {
728         ENSURE_READ_BYTES( 4 );
729         apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
730         apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
731       }
732       else
733       {
734         apaint->u.skew.center_x = 0;
735         apaint->u.skew.center_y = 0;
736       }
737 
738       apaint->format = FT_COLR_PAINTFORMAT_SKEW;
739 
740       return 1;
741     }
742 
743     else if ( apaint->format == FT_COLR_PAINTFORMAT_COMPOSITE )
744     {
745       FT_UInt  composite_mode;
746 
747 
748       apaint->u.composite.source_paint.p                     = child_table_p;
749       apaint->u.composite.source_paint.insert_root_transform = 0;
750 
751       ENSURE_READ_BYTES( 1 );
752       composite_mode = FT_NEXT_BYTE( p );
753       if ( composite_mode >= FT_COLR_COMPOSITE_MAX )
754         return 0;
755 
756       apaint->u.composite.composite_mode = (FT_Composite_Mode)composite_mode;
757 
758       if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
759          return 0;
760 
761       apaint->u.composite.backdrop_paint.p =
762         child_table_p;
763       apaint->u.composite.backdrop_paint.insert_root_transform =
764         0;
765 
766       return 1;
767     }
768 
769     return 0;
770   }
771 
772 
773   static FT_Bool
find_base_glyph_v1_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphV1Record * record)774   find_base_glyph_v1_record( FT_Byte *           base_glyph_begin,
775                              FT_UInt             num_base_glyph,
776                              FT_UInt             glyph_id,
777                              BaseGlyphV1Record  *record )
778   {
779     FT_UInt  min = 0;
780     FT_UInt  max = num_base_glyph;
781 
782 
783     while ( min < max )
784     {
785       FT_UInt  mid = min + ( max - min ) / 2;
786 
787       /*
788        * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
789        * skip `numBaseGlyphV1Records` by adding 4 to start binary search
790        * in the array of `BaseGlyphV1Record`.
791        */
792       FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
793 
794       FT_UShort  gid = FT_NEXT_USHORT( p );
795 
796 
797       if ( gid < glyph_id )
798         min = mid + 1;
799       else if (gid > glyph_id )
800         max = mid;
801       else
802       {
803         record->gid          = gid;
804         record->paint_offset = FT_NEXT_ULONG ( p );
805         return 1;
806       }
807     }
808 
809     return 0;
810   }
811 
812 
813   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)814   tt_face_get_colr_glyph_paint( TT_Face                  face,
815                                 FT_UInt                  base_glyph,
816                                 FT_Color_Root_Transform  root_transform,
817                                 FT_OpaquePaint*          opaque_paint )
818   {
819     Colr*              colr = (Colr*)face->colr;
820     BaseGlyphV1Record  base_glyph_v1_record;
821     FT_Byte*           p;
822 
823     if ( !colr || !colr->table )
824       return 0;
825 
826     if ( colr->version < 1 || !colr->num_base_glyphs_v1 ||
827          !colr->base_glyphs_v1 )
828       return 0;
829 
830     if ( opaque_paint->p )
831       return 0;
832 
833     if ( !find_base_glyph_v1_record( colr->base_glyphs_v1,
834                                      colr->num_base_glyphs_v1,
835                                      base_glyph,
836                                      &base_glyph_v1_record ) )
837       return 0;
838 
839     if ( !base_glyph_v1_record.paint_offset                   ||
840          base_glyph_v1_record.paint_offset > colr->table_size )
841       return 0;
842 
843     p = (FT_Byte*)( colr->base_glyphs_v1 +
844                     base_glyph_v1_record.paint_offset );
845     if ( p >= ( (FT_Byte*)colr->table + colr->table_size ) )
846       return 0;
847 
848     opaque_paint->p = p;
849 
850     if ( root_transform == FT_COLOR_INCLUDE_ROOT_TRANSFORM )
851       opaque_paint->insert_root_transform = 1;
852     else
853       opaque_paint->insert_root_transform = 0;
854 
855     return 1;
856   }
857 
858 
859   FT_LOCAL_DEF( FT_Bool )
tt_face_get_color_glyph_clipbox(TT_Face face,FT_UInt base_glyph,FT_ClipBox * clip_box)860   tt_face_get_color_glyph_clipbox( TT_Face      face,
861                                    FT_UInt      base_glyph,
862                                    FT_ClipBox*  clip_box )
863   {
864     Colr*  colr;
865 
866     FT_Byte  *p, *p1, *clip_base;
867 
868     FT_Byte    clip_list_format;
869     FT_ULong   num_clip_boxes, i;
870     FT_UShort  gid_start, gid_end;
871     FT_UInt32  clip_box_offset;
872     FT_Byte    format;
873 
874     const FT_Byte  num_corners = 4;
875     FT_Vector      corners[4];
876     FT_Byte        j;
877     FT_BBox        font_clip_box;
878 
879 
880     colr = (Colr*)face->colr;
881     if ( !colr )
882       return 0;
883 
884     if ( !colr->clip_list )
885       return 0;
886 
887     p = colr->clip_list;
888 
889     clip_base        = p;
890     clip_list_format = FT_NEXT_BYTE ( p );
891 
892     /* Format byte used here to be able to upgrade ClipList for >16bit */
893     /* glyph ids; for now we can expect it to be 0. */
894     if ( !( clip_list_format == 1 ) )
895       return 0;
896 
897     num_clip_boxes = FT_NEXT_ULONG( p );
898 
899     for ( i = 0; i < num_clip_boxes; ++i )
900     {
901       gid_start       = FT_NEXT_USHORT( p );
902       gid_end         = FT_NEXT_USHORT( p );
903       clip_box_offset = FT_NEXT_UOFF3( p );
904 
905       if ( base_glyph >= gid_start && base_glyph <= gid_end )
906       {
907         p1 = (FT_Byte*)( clip_base + clip_box_offset );
908 
909         if ( p1 >= ( (FT_Byte*)colr->table + colr->table_size ) )
910           return 0;
911 
912         format = FT_NEXT_BYTE( p1 );
913 
914         if ( format > 1 )
915           return 0;
916 
917         /* `face->root.size->metrics.x_scale` and `y_scale` are factors   */
918         /* that scale a font unit value in integers to a 26.6 fixed value */
919         /* according to the requested size, see for example               */
920         /* `ft_recompute_scaled_metrics`.                                 */
921         font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
922                                         face->root.size->metrics.x_scale );
923         font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
924                                         face->root.size->metrics.x_scale );
925         font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
926                                         face->root.size->metrics.x_scale );
927         font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
928                                         face->root.size->metrics.x_scale );
929 
930         /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */
931         /* them.  If we we would only transform two corner points and    */
932         /* span a rectangle based on those, the rectangle may become too */
933         /* small to cover the glyph.                                     */
934         corners[0].x = font_clip_box.xMin;
935         corners[1].x = font_clip_box.xMin;
936         corners[2].x = font_clip_box.xMax;
937         corners[3].x = font_clip_box.xMax;
938 
939         corners[0].y = font_clip_box.yMin;
940         corners[1].y = font_clip_box.yMax;
941         corners[2].y = font_clip_box.yMax;
942         corners[3].y = font_clip_box.yMin;
943 
944         for ( j = 0; j < num_corners; ++j )
945         {
946           if ( face->root.internal->transform_flags & 1 )
947             FT_Vector_Transform( &corners[j],
948                                  &face->root.internal->transform_matrix );
949 
950           if ( face->root.internal->transform_flags & 2 )
951           {
952             corners[j].x += face->root.internal->transform_delta.x;
953             corners[j].y += face->root.internal->transform_delta.y;
954           }
955         }
956 
957         clip_box->bottom_left  = corners[0];
958         clip_box->top_left     = corners[1];
959         clip_box->top_right    = corners[2];
960         clip_box->bottom_right = corners[3];
961 
962         return 1;
963       }
964     }
965 
966     return 0;
967   }
968 
969 
970   FT_LOCAL_DEF( FT_Bool )
tt_face_get_paint_layers(TT_Face face,FT_LayerIterator * iterator,FT_OpaquePaint * opaque_paint)971   tt_face_get_paint_layers( TT_Face            face,
972                             FT_LayerIterator*  iterator,
973                             FT_OpaquePaint*    opaque_paint )
974   {
975     FT_Byte*   p             = NULL;
976     FT_Byte*   p_first_layer = NULL;
977     FT_Byte*   p_paint       = NULL;
978     FT_UInt32  paint_offset;
979 
980     Colr*  colr;
981 
982 
983     if ( iterator->layer == iterator->num_layers )
984       return 0;
985 
986     colr = (Colr*)face->colr;
987     if ( !colr )
988       return 0;
989 
990     /*
991      * We have an iterator pointing at a paint offset as part of the
992      * `paintOffset` array in `LayerV1List`.
993      */
994     p = iterator->p;
995 
996     /*
997      * Do a cursor sanity check of the iterator.  Counting backwards from
998      * where it stands, we need to end up at a position after the beginning
999      * of the `LayerV1List` table and not after the end of the
1000      * `LayerV1List`.
1001      */
1002     p_first_layer = p -
1003                       iterator->layer * LAYER_V1_LIST_PAINT_OFFSET_SIZE -
1004                       LAYER_V1_LIST_NUM_LAYERS_SIZE;
1005     if ( p_first_layer < (FT_Byte*)colr->layers_v1 )
1006       return 0;
1007     if ( p_first_layer >= (FT_Byte*)(
1008            colr->layers_v1 + LAYER_V1_LIST_NUM_LAYERS_SIZE +
1009            colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) )
1010       return 0;
1011 
1012     /*
1013      * Before reading, ensure that `p` is within 'COLR' v1 and we can read a
1014      * 4-byte ULONG.
1015      */
1016     if ( p < colr->layers_v1                                  ||
1017          p > ( (FT_Byte*)colr->table + colr->table_size - 4 ) )
1018       return 0;
1019 
1020     paint_offset =
1021       FT_NEXT_ULONG( p );
1022     opaque_paint->insert_root_transform =
1023       0;
1024 
1025     p_paint = (FT_Byte*)( colr->layers_v1 + paint_offset );
1026 
1027     if ( p_paint < colr->paints_start_v1                         ||
1028          p_paint >= ( (FT_Byte*)colr->table + colr->table_size ) )
1029       return 0;
1030 
1031     opaque_paint->p = p_paint;
1032 
1033     iterator->p = p;
1034 
1035     iterator->layer++;
1036 
1037     return 1;
1038   }
1039 
1040 
1041   FT_LOCAL_DEF( FT_Bool )
tt_face_get_colorline_stops(TT_Face face,FT_ColorStop * color_stop,FT_ColorStopIterator * iterator)1042   tt_face_get_colorline_stops( TT_Face                face,
1043                                FT_ColorStop*          color_stop,
1044                                FT_ColorStopIterator  *iterator )
1045   {
1046     Colr*  colr = (Colr*)face->colr;
1047 
1048     FT_Byte*  p;
1049 
1050 
1051     if ( !colr || !colr->table )
1052       return 0;
1053 
1054     if ( iterator->current_color_stop >= iterator->num_color_stops )
1055       return 0;
1056 
1057     if ( iterator->p +
1058            ( ( iterator->num_color_stops - iterator->current_color_stop ) *
1059              COLOR_STOP_SIZE ) >
1060          ( (FT_Byte *)colr->table + colr->table_size ) )
1061       return 0;
1062 
1063     /* Iterator points at first `ColorStop` of `ColorLine`. */
1064     p = iterator->p;
1065 
1066     color_stop->stop_offset = FT_NEXT_SHORT( p );
1067 
1068     color_stop->color.palette_index = FT_NEXT_USHORT( p );
1069 
1070     color_stop->color.alpha = FT_NEXT_SHORT( p );
1071 
1072     iterator->p = p;
1073     iterator->current_color_stop++;
1074 
1075     return 1;
1076   }
1077 
1078 
1079   FT_LOCAL_DEF( FT_Bool )
tt_face_get_paint(TT_Face face,FT_OpaquePaint opaque_paint,FT_COLR_Paint * paint)1080   tt_face_get_paint( TT_Face         face,
1081                      FT_OpaquePaint  opaque_paint,
1082                      FT_COLR_Paint*  paint )
1083   {
1084     Colr*           colr = (Colr*)face->colr;
1085     FT_OpaquePaint  next_paint;
1086     FT_Matrix       ft_root_scale;
1087 
1088     if ( !colr || !colr->base_glyphs_v1 || !colr->table )
1089       return 0;
1090 
1091     if ( opaque_paint.insert_root_transform )
1092     {
1093       /* 'COLR' v1 glyph information is returned in unscaled coordinates,
1094        * i.e., `FT_Size` is not applied or multiplied into the values.  When
1095        * client applications draw color glyphs, they can request to include
1096        * a top-level transform, which includes the active `x_scale` and
1097        * `y_scale` information for scaling the glyph, as well the additional
1098        * transform and translate configured through `FT_Set_Transform`.
1099        * This allows client applications to apply this top-level transform
1100        * to the graphics context first and only once, then have gradient and
1101        * contour scaling applied correctly when performing the additional
1102        * drawing operations for subsequenct paints.  Prepare this initial
1103        * transform here.
1104        */
1105       paint->format = FT_COLR_PAINTFORMAT_TRANSFORM;
1106 
1107       next_paint.p                     = opaque_paint.p;
1108       next_paint.insert_root_transform = 0;
1109       paint->u.transform.paint         = next_paint;
1110 
1111       /* `x_scale` and `y_scale` are in 26.6 format, representing the scale
1112        * factor to get from font units to requested size.  However, expected
1113        * return values are in 16.16, so we shift accordingly with rounding.
1114        */
1115       ft_root_scale.xx = ( face->root.size->metrics.x_scale + 32 ) >> 6;
1116       ft_root_scale.xy = 0;
1117       ft_root_scale.yx = 0;
1118       ft_root_scale.yy = ( face->root.size->metrics.y_scale + 32 ) >> 6;
1119 
1120       if ( face->root.internal->transform_flags & 1 )
1121         FT_Matrix_Multiply( &face->root.internal->transform_matrix,
1122                             &ft_root_scale );
1123 
1124       paint->u.transform.affine.xx = ft_root_scale.xx;
1125       paint->u.transform.affine.xy = ft_root_scale.xy;
1126       paint->u.transform.affine.yx = ft_root_scale.yx;
1127       paint->u.transform.affine.yy = ft_root_scale.yy;
1128 
1129       /* The translation is specified in 26.6 format and, according to the
1130        * documentation of `FT_Set_Translate`, is performed on the character
1131        * size given in the last call to `FT_Set_Char_Size`.  The
1132        * 'PaintTransform' paint table's `FT_Affine23` format expects
1133        * values in 16.16 format, thus we need to shift by 10 bits.
1134        */
1135       if ( face->root.internal->transform_flags & 2 )
1136       {
1137         paint->u.transform.affine.dx =
1138           face->root.internal->transform_delta.x * ( 1 << 10 );
1139         paint->u.transform.affine.dy =
1140           face->root.internal->transform_delta.y * ( 1 << 10 );
1141       }
1142       else
1143       {
1144         paint->u.transform.affine.dx = 0;
1145         paint->u.transform.affine.dy = 0;
1146       }
1147 
1148       return 1;
1149     }
1150 
1151     return read_paint( colr, opaque_paint.p, paint );
1152   }
1153 
1154 
1155   FT_LOCAL_DEF( FT_Error )
tt_face_colr_blend_layer(TT_Face face,FT_UInt color_index,FT_GlyphSlot dstSlot,FT_GlyphSlot srcSlot)1156   tt_face_colr_blend_layer( TT_Face       face,
1157                             FT_UInt       color_index,
1158                             FT_GlyphSlot  dstSlot,
1159                             FT_GlyphSlot  srcSlot )
1160   {
1161     FT_Error  error;
1162 
1163     FT_UInt  x, y;
1164     FT_Byte  b, g, r, alpha;
1165 
1166     FT_ULong  size;
1167     FT_Byte*  src;
1168     FT_Byte*  dst;
1169 
1170 
1171     if ( !dstSlot->bitmap.buffer )
1172     {
1173       /* Initialize destination of color bitmap */
1174       /* with the size of first component.      */
1175       dstSlot->bitmap_left = srcSlot->bitmap_left;
1176       dstSlot->bitmap_top  = srcSlot->bitmap_top;
1177 
1178       dstSlot->bitmap.width      = srcSlot->bitmap.width;
1179       dstSlot->bitmap.rows       = srcSlot->bitmap.rows;
1180       dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
1181       dstSlot->bitmap.pitch      = (int)dstSlot->bitmap.width * 4;
1182       dstSlot->bitmap.num_grays  = 256;
1183 
1184       size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch;
1185 
1186       error = ft_glyphslot_alloc_bitmap( dstSlot, size );
1187       if ( error )
1188         return error;
1189 
1190       FT_MEM_ZERO( dstSlot->bitmap.buffer, size );
1191     }
1192     else
1193     {
1194       /* Resize destination if needed such that new component fits. */
1195       FT_Int  x_min, x_max, y_min, y_max;
1196 
1197 
1198       x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left );
1199       x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width,
1200                       srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width );
1201 
1202       y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows,
1203                       srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows );
1204       y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top );
1205 
1206       if ( x_min != dstSlot->bitmap_left                                 ||
1207            x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width ||
1208            y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows   ||
1209            y_max != dstSlot->bitmap_top                                  )
1210       {
1211         FT_Memory  memory = face->root.memory;
1212 
1213         FT_UInt  width = (FT_UInt)( x_max - x_min );
1214         FT_UInt  rows  = (FT_UInt)( y_max - y_min );
1215         FT_UInt  pitch = width * 4;
1216 
1217         FT_Byte*  buf = NULL;
1218         FT_Byte*  p;
1219         FT_Byte*  q;
1220 
1221 
1222         size  = rows * pitch;
1223         if ( FT_ALLOC( buf, size ) )
1224           return error;
1225 
1226         p = dstSlot->bitmap.buffer;
1227         q = buf +
1228             (int)pitch * ( y_max - dstSlot->bitmap_top ) +
1229             4 * ( dstSlot->bitmap_left - x_min );
1230 
1231         for ( y = 0; y < dstSlot->bitmap.rows; y++ )
1232         {
1233           FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 );
1234 
1235           p += dstSlot->bitmap.pitch;
1236           q += pitch;
1237         }
1238 
1239         ft_glyphslot_set_bitmap( dstSlot, buf );
1240 
1241         dstSlot->bitmap_top  = y_max;
1242         dstSlot->bitmap_left = x_min;
1243 
1244         dstSlot->bitmap.width = width;
1245         dstSlot->bitmap.rows  = rows;
1246         dstSlot->bitmap.pitch = (int)pitch;
1247 
1248         dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP;
1249         dstSlot->format           = FT_GLYPH_FORMAT_BITMAP;
1250       }
1251     }
1252 
1253     if ( color_index == 0xFFFF )
1254     {
1255       if ( face->have_foreground_color )
1256       {
1257         b     = face->foreground_color.blue;
1258         g     = face->foreground_color.green;
1259         r     = face->foreground_color.red;
1260         alpha = face->foreground_color.alpha;
1261       }
1262       else
1263       {
1264         if ( face->palette_data.palette_flags                          &&
1265              ( face->palette_data.palette_flags[face->palette_index] &
1266                  FT_PALETTE_FOR_DARK_BACKGROUND                      ) )
1267         {
1268           /* white opaque */
1269           b     = 0xFF;
1270           g     = 0xFF;
1271           r     = 0xFF;
1272           alpha = 0xFF;
1273         }
1274         else
1275         {
1276           /* black opaque */
1277           b     = 0x00;
1278           g     = 0x00;
1279           r     = 0x00;
1280           alpha = 0xFF;
1281         }
1282       }
1283     }
1284     else
1285     {
1286       b     = face->palette[color_index].blue;
1287       g     = face->palette[color_index].green;
1288       r     = face->palette[color_index].red;
1289       alpha = face->palette[color_index].alpha;
1290     }
1291 
1292     /* XXX Convert if srcSlot.bitmap is not grey? */
1293     src = srcSlot->bitmap.buffer;
1294     dst = dstSlot->bitmap.buffer +
1295           dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) +
1296           4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left );
1297 
1298     for ( y = 0; y < srcSlot->bitmap.rows; y++ )
1299     {
1300       for ( x = 0; x < srcSlot->bitmap.width; x++ )
1301       {
1302         int  aa = src[x];
1303         int  fa = alpha * aa / 255;
1304 
1305         int  fb = b * fa / 255;
1306         int  fg = g * fa / 255;
1307         int  fr = r * fa / 255;
1308 
1309         int  ba2 = 255 - fa;
1310 
1311         int  bb = dst[4 * x + 0];
1312         int  bg = dst[4 * x + 1];
1313         int  br = dst[4 * x + 2];
1314         int  ba = dst[4 * x + 3];
1315 
1316 
1317         dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb );
1318         dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg );
1319         dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr );
1320         dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa );
1321       }
1322 
1323       src += srcSlot->bitmap.pitch;
1324       dst += dstSlot->bitmap.pitch;
1325     }
1326 
1327     return FT_Err_Ok;
1328   }
1329 
1330 #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
1331 
1332   /* ANSI C doesn't like empty source files */
1333   typedef int  _tt_colr_dummy;
1334 
1335 #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
1336 
1337 /* EOF */
1338