Coverage Report

Created: 2021-08-22 09:07

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