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