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