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 ) tt_face_load_colr(TT_Face face,FT_Stream stream)159 tt_face_load_colr( TT_Face face, 160 FT_Stream stream ) 161 { 162 FT_Error error; 163 FT_Memory memory = face->root.memory; 164 165 FT_Byte* table = NULL; 166 FT_Byte* p = NULL; 167 /* Needed for reading array lengths in referenced tables. */ 168 FT_Byte* p1 = NULL; 169 170 Colr* colr = NULL; 171 172 FT_ULong base_glyph_offset, layer_offset; 173 FT_ULong base_glyphs_offset_v1, num_base_glyphs_v1; 174 FT_ULong layer_offset_v1, num_layers_v1, clip_list_offset; 175 FT_ULong table_size; 176 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 177 FT_ULong colr_offset_in_stream; 178 #endif 179 180 181 /* `COLR' always needs `CPAL' */ 182 if ( !face->cpal ) 183 return FT_THROW( Invalid_File_Format ); 184 185 error = face->goto_table( face, TTAG_COLR, stream, &table_size ); 186 if ( error ) 187 goto NoColr; 188 189 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 190 colr_offset_in_stream = FT_STREAM_POS(); 191 #endif 192 193 if ( table_size < COLRV0_HEADER_SIZE ) 194 goto NoColr; 195 196 if ( FT_FRAME_EXTRACT( table_size, table ) ) 197 goto NoColr; 198 199 p = table; 200 201 if ( FT_NEW( colr ) ) 202 goto NoColr; 203 204 colr->version = FT_NEXT_USHORT( p ); 205 if ( colr->version != 0 && colr->version != 1 ) 206 goto InvalidTable; 207 208 colr->num_base_glyphs = FT_NEXT_USHORT( p ); 209 base_glyph_offset = FT_NEXT_ULONG( p ); 210 211 if ( 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 ) tt_face_free_colr(TT_Face face)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 find_base_glyph_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphRecord * record)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 ) tt_face_get_colr_layer(TT_Face face,FT_UInt base_glyph,FT_UInt * aglyph_index,FT_UInt * acolor_index,FT_LayerIterator * iterator)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 read_color_line(Colr * colr,FT_Byte * color_line_p,FT_ColorLine * colorline,FT_Bool read_variable)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 get_child_table_pointer(Colr * colr,FT_Byte * paint_base,FT_Byte ** p,FT_Byte ** child_table_pointer)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 get_deltas_for_var_index_base(TT_Face face,Colr * colr,FT_ULong var_index_base,FT_UInt num_deltas,FT_ItemVarDelta * deltas)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 read_paint(TT_Face face,Colr * colr,FT_Byte * p,FT_COLR_Paint * apaint)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 find_base_glyph_v1_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphV1Record * record)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 ) tt_face_get_colr_glyph_paint(TT_Face face,FT_UInt base_glyph,FT_Color_Root_Transform root_transform,FT_OpaquePaint * opaque_paint)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 ) tt_face_get_color_glyph_clipbox(TT_Face face,FT_UInt base_glyph,FT_ClipBox * clip_box)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 ) tt_face_get_paint_layers(TT_Face face,FT_LayerIterator * iterator,FT_OpaquePaint * opaque_paint)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 ) tt_face_get_colorline_stops(TT_Face face,FT_ColorStop * color_stop,FT_ColorStopIterator * iterator)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 ) tt_face_get_paint(TT_Face face,FT_OpaquePaint opaque_paint,FT_COLR_Paint * paint)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 ) tt_face_colr_blend_layer(TT_Face face,FT_UInt color_index,FT_GlyphSlot dstSlot,FT_GlyphSlot srcSlot)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