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 <[email protected]>. 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 ( 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 ) tt_face_free_colr(TT_Face face)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 find_base_glyph_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphRecord * record)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 ) tt_face_get_colr_layer(TT_Face face,FT_UInt base_glyph,FT_UInt * aglyph_index,FT_UInt * acolor_index,FT_LayerIterator * iterator)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 read_color_line(Colr * colr,FT_Byte * color_line_p,FT_ColorLine * colorline,FT_Bool read_variable)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 get_child_table_pointer(Colr * colr,FT_Byte * paint_base,FT_Byte ** p,FT_Byte ** child_table_pointer)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 get_deltas_for_var_index_base(TT_Face face,Colr * colr,FT_ULong var_index_base,FT_UInt num_deltas,FT_ItemVarDelta * deltas)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 read_paint(TT_Face face,Colr * colr,FT_Byte * p,FT_COLR_Paint * apaint)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 num_layers = FT_NEXT_BYTE( p ); 666 if ( num_layers > colr->num_layers_v1 ) 667 return 0; 668 669 first_layer_index = FT_NEXT_ULONG( p ); 670 if ( first_layer_index + num_layers > colr->num_layers_v1 ) 671 return 0; 672 673 apaint->u.colr_layers.layer_iterator.num_layers = num_layers; 674 apaint->u.colr_layers.layer_iterator.layer = 0; 675 /* TODO: Check whether pointer is outside colr? */ 676 apaint->u.colr_layers.layer_iterator.p = 677 colr->layers_v1 + 678 LAYER_V1_LIST_NUM_LAYERS_SIZE + 679 LAYER_V1_LIST_PAINT_OFFSET_SIZE * first_layer_index; 680 681 return 1; 682 } 683 684 else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID || 685 (FT_PaintFormat_Internal)apaint->format == 686 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID ) 687 { 688 ENSURE_READ_BYTES( 4 ); 689 apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p ); 690 apaint->u.solid.color.alpha = FT_NEXT_SHORT( p ); 691 692 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 693 if ( (FT_PaintFormat_Internal)apaint->format == 694 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID ) 695 { 696 ENSURE_READ_BYTES( 4 ); 697 var_index_base = FT_NEXT_ULONG( p ); 698 699 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1, 700 item_deltas ) ) 701 return 0; 702 703 apaint->u.solid.color.alpha += (FT_F2Dot14)item_deltas[0]; 704 } 705 #endif 706 707 apaint->format = FT_COLR_PAINTFORMAT_SOLID; 708 709 return 1; 710 } 711 712 else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH ) 713 { 714 ENSURE_READ_BYTES(2); 715 apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p ); 716 717 return 1; 718 } 719 720 /* 721 * Grouped below here are all paint formats that have an offset to a 722 * child paint table as the first entry (for example, a color line or a 723 * child paint table). Retrieve that and determine whether that paint 724 * offset is valid first. 725 */ 726 727 if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) 728 return 0; 729 730 if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT || 731 ( do_read_var = 732 ( (FT_PaintFormat_Internal)apaint->format == 733 FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT ) ) ) 734 { 735 if ( !read_color_line( colr, 736 child_table_p, 737 &apaint->u.linear_gradient.colorline, 738 do_read_var ) ) 739 return 0; 740 741 /* 742 * In order to support variations expose these as FT_Fixed 16.16 743 * values so that we can support fractional values after 744 * interpolation. 745 */ 746 ENSURE_READ_BYTES( 12 ); 747 apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 748 apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 749 apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 750 apaint->u.linear_gradient.p1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 751 apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 752 apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 753 754 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 755 if ( do_read_var ) 756 { 757 ENSURE_READ_BYTES( 4 ); 758 var_index_base = FT_NEXT_ULONG ( p ); 759 760 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, 761 item_deltas ) ) 762 return 0; 763 764 apaint->u.linear_gradient.p0.x += INT_TO_FIXED( item_deltas[0] ); 765 apaint->u.linear_gradient.p0.y += INT_TO_FIXED( item_deltas[1] ); 766 apaint->u.linear_gradient.p1.x += INT_TO_FIXED( item_deltas[2] ); 767 apaint->u.linear_gradient.p1.y += INT_TO_FIXED( item_deltas[3] ); 768 apaint->u.linear_gradient.p2.x += INT_TO_FIXED( item_deltas[4] ); 769 apaint->u.linear_gradient.p2.y += INT_TO_FIXED( item_deltas[5] ); 770 } 771 #endif 772 773 apaint->format = FT_COLR_PAINTFORMAT_LINEAR_GRADIENT; 774 775 return 1; 776 } 777 778 else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT || 779 ( do_read_var = 780 ( (FT_PaintFormat_Internal)apaint->format == 781 FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT ) ) ) 782 { 783 FT_Pos tmp; 784 785 786 if ( !read_color_line( colr, 787 child_table_p, 788 &apaint->u.radial_gradient.colorline, 789 do_read_var ) ) 790 return 0; 791 792 793 /* In the OpenType specification, `r0` and `r1` are defined as */ 794 /* `UFWORD`. Since FreeType doesn't have a corresponding 16.16 */ 795 /* format we convert to `FWORD` and replace negative values with */ 796 /* (32bit) `FT_INT_MAX`. */ 797 798 ENSURE_READ_BYTES( 12 ); 799 800 apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 801 apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 802 803 tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 804 apaint->u.radial_gradient.r0 = tmp < 0 ? FT_INT_MAX : tmp; 805 806 apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 807 apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 808 809 tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 810 apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp; 811 812 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 813 if ( do_read_var ) 814 { 815 ENSURE_READ_BYTES( 4 ); 816 var_index_base = FT_NEXT_ULONG ( p ); 817 818 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, 819 item_deltas ) ) 820 return 0; 821 822 apaint->u.radial_gradient.c0.x += INT_TO_FIXED( item_deltas[0] ); 823 apaint->u.radial_gradient.c0.y += INT_TO_FIXED( item_deltas[1] ); 824 825 // TODO: Anything to be done about UFWORD deltas here? 826 apaint->u.radial_gradient.r0 += INT_TO_FIXED( item_deltas[2] ); 827 828 apaint->u.radial_gradient.c1.x += INT_TO_FIXED( item_deltas[3] ); 829 apaint->u.radial_gradient.c1.y += INT_TO_FIXED( item_deltas[4] ); 830 831 apaint->u.radial_gradient.r1 += INT_TO_FIXED( item_deltas[5] ); 832 } 833 #endif 834 835 apaint->format = FT_COLR_PAINTFORMAT_RADIAL_GRADIENT; 836 837 return 1; 838 } 839 840 else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT || 841 ( do_read_var = 842 ( (FT_PaintFormat_Internal)apaint->format == 843 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT ) ) ) 844 { 845 if ( !read_color_line( colr, 846 child_table_p, 847 &apaint->u.sweep_gradient.colorline, 848 do_read_var) ) 849 return 0; 850 851 ENSURE_READ_BYTES( 8 ); 852 853 apaint->u.sweep_gradient.center.x = 854 INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 855 apaint->u.sweep_gradient.center.y = 856 INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 857 858 apaint->u.sweep_gradient.start_angle = 859 F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 860 apaint->u.sweep_gradient.end_angle = 861 F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 862 863 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 864 if ( do_read_var ) 865 { 866 ENSURE_READ_BYTES( 4 ); 867 var_index_base = FT_NEXT_ULONG ( p ); 868 869 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, 870 item_deltas ) ) 871 return 0; 872 873 // TODO: Handle overflow? 874 apaint->u.sweep_gradient.center.x += INT_TO_FIXED( item_deltas[0] ); 875 apaint->u.sweep_gradient.center.y += INT_TO_FIXED( item_deltas[1] ); 876 877 apaint->u.sweep_gradient.start_angle += 878 F2DOT14_TO_FIXED( item_deltas[2] ); 879 apaint->u.sweep_gradient.end_angle += 880 F2DOT14_TO_FIXED( item_deltas[3] ); 881 } 882 #endif 883 apaint->format = FT_COLR_PAINTFORMAT_SWEEP_GRADIENT; 884 885 return 1; 886 } 887 888 if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH ) 889 { 890 ENSURE_READ_BYTES( 2 ); 891 apaint->u.glyph.paint.p = child_table_p; 892 apaint->u.glyph.paint.insert_root_transform = 0; 893 apaint->u.glyph.glyphID = FT_NEXT_USHORT( p ); 894 895 return 1; 896 } 897 898 else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM || 899 (FT_PaintFormat_Internal)apaint->format == 900 FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM ) 901 { 902 apaint->u.transform.paint.p = child_table_p; 903 apaint->u.transform.paint.insert_root_transform = 0; 904 905 if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) 906 return 0; 907 908 p = child_table_p; 909 910 /* 911 * The following matrix coefficients are encoded as 912 * OpenType 16.16 fixed-point values. 913 */ 914 ENSURE_READ_BYTES( 24 ); 915 apaint->u.transform.affine.xx = FT_NEXT_LONG( p ); 916 apaint->u.transform.affine.yx = FT_NEXT_LONG( p ); 917 apaint->u.transform.affine.xy = FT_NEXT_LONG( p ); 918 apaint->u.transform.affine.yy = FT_NEXT_LONG( p ); 919 apaint->u.transform.affine.dx = FT_NEXT_LONG( p ); 920 apaint->u.transform.affine.dy = FT_NEXT_LONG( p ); 921 922 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 923 if ( (FT_PaintFormat_Internal)apaint->format == 924 FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSFORM ) 925 { 926 ENSURE_READ_BYTES( 4 ); 927 var_index_base = FT_NEXT_ULONG( p ); 928 929 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 6, 930 item_deltas ) ) 931 return 0; 932 933 apaint->u.transform.affine.xx += (FT_Fixed)item_deltas[0]; 934 apaint->u.transform.affine.yx += (FT_Fixed)item_deltas[1]; 935 apaint->u.transform.affine.xy += (FT_Fixed)item_deltas[2]; 936 apaint->u.transform.affine.yy += (FT_Fixed)item_deltas[3]; 937 apaint->u.transform.affine.dx += (FT_Fixed)item_deltas[4]; 938 apaint->u.transform.affine.dy += (FT_Fixed)item_deltas[5]; 939 } 940 #endif 941 942 apaint->format = FT_COLR_PAINTFORMAT_TRANSFORM; 943 944 return 1; 945 } 946 947 else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE || 948 (FT_PaintFormat_Internal)apaint->format == 949 FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE ) 950 { 951 apaint->u.translate.paint.p = child_table_p; 952 apaint->u.translate.paint.insert_root_transform = 0; 953 954 ENSURE_READ_BYTES( 4 ); 955 apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 956 apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 957 958 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 959 if ( (FT_PaintFormat_Internal)apaint->format == 960 FT_COLR_PAINTFORMAT_INTERNAL_VAR_TRANSLATE ) 961 { 962 ENSURE_READ_BYTES( 4 ); 963 var_index_base = FT_NEXT_ULONG( p ); 964 965 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, 966 item_deltas ) ) 967 return 0; 968 969 apaint->u.translate.dx += INT_TO_FIXED( item_deltas[0] ); 970 apaint->u.translate.dy += INT_TO_FIXED( item_deltas[1] ); 971 } 972 #endif 973 974 apaint->format = FT_COLR_PAINTFORMAT_TRANSLATE; 975 976 return 1; 977 } 978 979 else if ( apaint->format >= FT_COLR_PAINTFORMAT_SCALE && 980 (FT_PaintFormat_Internal)apaint->format <= 981 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) 982 { 983 apaint->u.scale.paint.p = child_table_p; 984 apaint->u.scale.paint.insert_root_transform = 0; 985 986 /* All scale paints get at least one scale value. */ 987 ENSURE_READ_BYTES( 2 ); 988 apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 989 990 /* Non-uniform ones read an extra y value. */ 991 if ( apaint->format == FT_COLR_PAINTFORMAT_SCALE || 992 (FT_PaintFormat_Internal)apaint->format == 993 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE || 994 (FT_PaintFormat_Internal)apaint->format == 995 FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || 996 (FT_PaintFormat_Internal)apaint->format == 997 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER ) 998 { 999 ENSURE_READ_BYTES( 2 ); 1000 apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 1001 } 1002 else 1003 apaint->u.scale.scale_y = apaint->u.scale.scale_x; 1004 1005 /* Scale paints that have a center read center coordinates, */ 1006 /* otherwise the center is (0,0). */ 1007 if ( (FT_PaintFormat_Internal)apaint->format == 1008 FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER || 1009 (FT_PaintFormat_Internal)apaint->format == 1010 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER || 1011 (FT_PaintFormat_Internal)apaint->format == 1012 FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER || 1013 (FT_PaintFormat_Internal)apaint->format == 1014 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) 1015 { 1016 ENSURE_READ_BYTES( 4 ); 1017 apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); 1018 apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) ); 1019 } 1020 else 1021 { 1022 apaint->u.scale.center_x = 0; 1023 apaint->u.scale.center_y = 0; 1024 } 1025 1026 /* Base values set, now handle variations. */ 1027 1028 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1029 if ( (FT_PaintFormat_Internal)apaint->format == 1030 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE || 1031 (FT_PaintFormat_Internal)apaint->format == 1032 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER || 1033 (FT_PaintFormat_Internal)apaint->format == 1034 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM || 1035 (FT_PaintFormat_Internal)apaint->format == 1036 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) 1037 { 1038 ENSURE_READ_BYTES( 4 ); 1039 var_index_base = FT_NEXT_ULONG( p ); 1040 1041 if ( (FT_PaintFormat_Internal)apaint->format == 1042 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE ) 1043 { 1044 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, 1045 item_deltas ) ) 1046 return 0; 1047 1048 apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); 1049 apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] ); 1050 } 1051 1052 if ( (FT_PaintFormat_Internal)apaint->format == 1053 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_CENTER ) 1054 { 1055 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, 1056 item_deltas ) ) 1057 return 0; 1058 1059 apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); 1060 apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[1] ); 1061 apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[2] ); 1062 apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[3] ); 1063 } 1064 1065 if ( (FT_PaintFormat_Internal)apaint->format == 1066 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM ) 1067 { 1068 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1, 1069 item_deltas ) ) 1070 return 0; 1071 1072 apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); 1073 apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] ); 1074 } 1075 1076 if ( (FT_PaintFormat_Internal)apaint->format == 1077 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SCALE_UNIFORM_CENTER ) 1078 { 1079 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 3, 1080 item_deltas ) ) 1081 return 0; 1082 1083 apaint->u.scale.scale_x += F2DOT14_TO_FIXED( item_deltas[0] ); 1084 apaint->u.scale.scale_y += F2DOT14_TO_FIXED( item_deltas[0] ); 1085 apaint->u.scale.center_x += INT_TO_FIXED( item_deltas[1] ); 1086 apaint->u.scale.center_y += INT_TO_FIXED( item_deltas[2] ); 1087 } 1088 } 1089 #endif 1090 1091 /* FT 'COLR' v1 API output format always returns fully defined */ 1092 /* structs; we thus set the format to the public API value. */ 1093 apaint->format = FT_COLR_PAINTFORMAT_SCALE; 1094 1095 return 1; 1096 } 1097 1098 else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE || 1099 (FT_PaintFormat_Internal)apaint->format == 1100 FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER || 1101 (FT_PaintFormat_Internal)apaint->format == 1102 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE || 1103 (FT_PaintFormat_Internal)apaint->format == 1104 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) 1105 { 1106 apaint->u.rotate.paint.p = child_table_p; 1107 apaint->u.rotate.paint.insert_root_transform = 0; 1108 1109 ENSURE_READ_BYTES( 2 ); 1110 apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 1111 1112 if ( (FT_PaintFormat_Internal)apaint->format == 1113 FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER || 1114 (FT_PaintFormat_Internal)apaint->format == 1115 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) 1116 { 1117 ENSURE_READ_BYTES( 4 ); 1118 apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 1119 apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 1120 } 1121 else 1122 { 1123 apaint->u.rotate.center_x = 0; 1124 apaint->u.rotate.center_y = 0; 1125 } 1126 1127 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1128 if ( (FT_PaintFormat_Internal)apaint->format == 1129 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE || 1130 (FT_PaintFormat_Internal)apaint->format == 1131 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) 1132 { 1133 FT_UInt num_deltas = 0; 1134 1135 1136 ENSURE_READ_BYTES( 4 ); 1137 var_index_base = FT_NEXT_ULONG( p ); 1138 1139 if ( (FT_PaintFormat_Internal)apaint->format == 1140 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE_CENTER ) 1141 num_deltas = 3; 1142 if ( (FT_PaintFormat_Internal)apaint->format == 1143 FT_COLR_PAINTFORMAT_INTERNAL_VAR_ROTATE ) 1144 num_deltas = 1; 1145 1146 if ( num_deltas > 0 ) 1147 { 1148 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 1149 num_deltas, item_deltas ) ) 1150 return 0; 1151 1152 apaint->u.rotate.angle += F2DOT14_TO_FIXED( item_deltas[0] ); 1153 1154 if ( num_deltas == 3 ) 1155 { 1156 apaint->u.rotate.center_x += INT_TO_FIXED( item_deltas[1] ); 1157 apaint->u.rotate.center_y += INT_TO_FIXED( item_deltas[2] ); 1158 } 1159 } 1160 } 1161 #endif 1162 1163 apaint->format = FT_COLR_PAINTFORMAT_ROTATE; 1164 1165 1166 return 1; 1167 } 1168 1169 else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW || 1170 (FT_PaintFormat_Internal)apaint->format == 1171 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW || 1172 (FT_PaintFormat_Internal)apaint->format == 1173 FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER || 1174 (FT_PaintFormat_Internal)apaint->format == 1175 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) 1176 { 1177 apaint->u.skew.paint.p = child_table_p; 1178 apaint->u.skew.paint.insert_root_transform = 0; 1179 1180 ENSURE_READ_BYTES( 4 ); 1181 apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 1182 apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 1183 1184 if ( (FT_PaintFormat_Internal)apaint->format == 1185 FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER || 1186 (FT_PaintFormat_Internal)apaint->format == 1187 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) 1188 { 1189 ENSURE_READ_BYTES( 4 ); 1190 apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 1191 apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) ); 1192 } 1193 else 1194 { 1195 apaint->u.skew.center_x = 0; 1196 apaint->u.skew.center_y = 0; 1197 } 1198 1199 1200 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1201 if ( (FT_PaintFormat_Internal)apaint->format == 1202 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW || 1203 (FT_PaintFormat_Internal)apaint->format == 1204 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) 1205 { 1206 ENSURE_READ_BYTES( 4 ); 1207 var_index_base = FT_NEXT_ULONG( p ); 1208 1209 if ( (FT_PaintFormat_Internal)apaint->format == 1210 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW ) 1211 { 1212 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 2, 1213 item_deltas ) ) 1214 return 0; 1215 1216 apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] ); 1217 apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] ); 1218 } 1219 1220 if ( (FT_PaintFormat_Internal)apaint->format == 1221 FT_COLR_PAINTFORMAT_INTERNAL_VAR_SKEW_CENTER ) 1222 { 1223 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, 1224 item_deltas ) ) 1225 return 0; 1226 1227 apaint->u.skew.x_skew_angle += F2DOT14_TO_FIXED( item_deltas[0] ); 1228 apaint->u.skew.y_skew_angle += F2DOT14_TO_FIXED( item_deltas[1] ); 1229 apaint->u.skew.center_x += INT_TO_FIXED( item_deltas[2] ); 1230 apaint->u.skew.center_y += INT_TO_FIXED( item_deltas[3] ); 1231 } 1232 } 1233 #endif 1234 1235 apaint->format = FT_COLR_PAINTFORMAT_SKEW; 1236 1237 return 1; 1238 } 1239 1240 else if ( apaint->format == FT_COLR_PAINTFORMAT_COMPOSITE ) 1241 { 1242 FT_UInt composite_mode; 1243 1244 1245 apaint->u.composite.source_paint.p = child_table_p; 1246 apaint->u.composite.source_paint.insert_root_transform = 0; 1247 1248 ENSURE_READ_BYTES( 1 ); 1249 composite_mode = FT_NEXT_BYTE( p ); 1250 if ( composite_mode >= FT_COLR_COMPOSITE_MAX ) 1251 return 0; 1252 1253 apaint->u.composite.composite_mode = (FT_Composite_Mode)composite_mode; 1254 1255 if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) ) 1256 return 0; 1257 1258 apaint->u.composite.backdrop_paint.p = 1259 child_table_p; 1260 apaint->u.composite.backdrop_paint.insert_root_transform = 1261 0; 1262 1263 return 1; 1264 } 1265 1266 return 0; 1267 } 1268 1269 1270 static FT_Bool find_base_glyph_v1_record(FT_Byte * base_glyph_begin,FT_UInt num_base_glyph,FT_UInt glyph_id,BaseGlyphV1Record * record)1271 find_base_glyph_v1_record( FT_Byte * base_glyph_begin, 1272 FT_UInt num_base_glyph, 1273 FT_UInt glyph_id, 1274 BaseGlyphV1Record *record ) 1275 { 1276 FT_UInt min = 0; 1277 FT_UInt max = num_base_glyph; 1278 1279 1280 while ( min < max ) 1281 { 1282 FT_UInt mid = min + ( max - min ) / 2; 1283 1284 /* 1285 * `base_glyph_begin` is the beginning of `BaseGlyphV1List`; 1286 * skip `numBaseGlyphV1Records` by adding 4 to start binary search 1287 * in the array of `BaseGlyphV1Record`. 1288 */ 1289 FT_Byte *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE; 1290 1291 FT_UShort gid = FT_NEXT_USHORT( p ); 1292 1293 1294 if ( gid < glyph_id ) 1295 min = mid + 1; 1296 else if (gid > glyph_id ) 1297 max = mid; 1298 else 1299 { 1300 record->gid = gid; 1301 record->paint_offset = FT_NEXT_ULONG ( p ); 1302 return 1; 1303 } 1304 } 1305 1306 return 0; 1307 } 1308 1309 1310 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)1311 tt_face_get_colr_glyph_paint( TT_Face face, 1312 FT_UInt base_glyph, 1313 FT_Color_Root_Transform root_transform, 1314 FT_OpaquePaint* opaque_paint ) 1315 { 1316 Colr* colr = (Colr*)face->colr; 1317 BaseGlyphV1Record base_glyph_v1_record; 1318 FT_Byte* p; 1319 1320 if ( !colr || !colr->table ) 1321 return 0; 1322 1323 if ( colr->version < 1 || !colr->num_base_glyphs_v1 || 1324 !colr->base_glyphs_v1 ) 1325 return 0; 1326 1327 if ( opaque_paint->p ) 1328 return 0; 1329 1330 if ( !find_base_glyph_v1_record( colr->base_glyphs_v1, 1331 colr->num_base_glyphs_v1, 1332 base_glyph, 1333 &base_glyph_v1_record ) ) 1334 return 0; 1335 1336 if ( !base_glyph_v1_record.paint_offset || 1337 base_glyph_v1_record.paint_offset > colr->table_size ) 1338 return 0; 1339 1340 p = (FT_Byte*)( colr->base_glyphs_v1 + 1341 base_glyph_v1_record.paint_offset ); 1342 if ( p >= ( (FT_Byte*)colr->table + colr->table_size ) ) 1343 return 0; 1344 1345 opaque_paint->p = p; 1346 1347 if ( root_transform == FT_COLOR_INCLUDE_ROOT_TRANSFORM ) 1348 opaque_paint->insert_root_transform = 1; 1349 else 1350 opaque_paint->insert_root_transform = 0; 1351 1352 return 1; 1353 } 1354 1355 1356 FT_LOCAL_DEF( FT_Bool ) tt_face_get_color_glyph_clipbox(TT_Face face,FT_UInt base_glyph,FT_ClipBox * clip_box)1357 tt_face_get_color_glyph_clipbox( TT_Face face, 1358 FT_UInt base_glyph, 1359 FT_ClipBox* clip_box ) 1360 { 1361 Colr* colr; 1362 1363 FT_Byte *p, *p1, *clip_base, *limit; 1364 1365 FT_Byte clip_list_format; 1366 FT_ULong num_clip_boxes, i; 1367 FT_UShort gid_start, gid_end; 1368 FT_UInt32 clip_box_offset; 1369 FT_Byte format; 1370 1371 const FT_Byte num_corners = 4; 1372 FT_Vector corners[4]; 1373 FT_Byte j; 1374 FT_BBox font_clip_box; 1375 1376 1377 colr = (Colr*)face->colr; 1378 if ( !colr ) 1379 return 0; 1380 1381 if ( !colr->clip_list ) 1382 return 0; 1383 1384 p = colr->clip_list; 1385 1386 /* Limit points to the first byte after the end of the color table. */ 1387 /* Thus, in subsequent limit checks below we need to check whether the */ 1388 /* read pointer is strictly greater than a position offset by certain */ 1389 /* field sizes to the left of that position. */ 1390 limit = (FT_Byte*)colr->table + colr->table_size; 1391 1392 /* Check whether we can extract one `uint8` and one `uint32`. */ 1393 if ( p > limit - ( 1 + 4 ) ) 1394 return 0; 1395 1396 clip_base = p; 1397 clip_list_format = FT_NEXT_BYTE ( p ); 1398 1399 /* Format byte used here to be able to upgrade ClipList for >16bit */ 1400 /* glyph ids; for now we can expect it to be 1. */ 1401 if ( !( clip_list_format == 1 ) ) 1402 return 0; 1403 1404 num_clip_boxes = FT_NEXT_ULONG( p ); 1405 1406 /* Check whether we can extract two `uint16` and one `Offset24`, */ 1407 /* `num_clip_boxes` times. */ 1408 if ( colr->table_size / ( 2 + 2 + 3 ) < num_clip_boxes || 1409 p > limit - ( 2 + 2 + 3 ) * num_clip_boxes ) 1410 return 0; 1411 1412 for ( i = 0; i < num_clip_boxes; ++i ) 1413 { 1414 gid_start = FT_NEXT_USHORT( p ); 1415 gid_end = FT_NEXT_USHORT( p ); 1416 clip_box_offset = FT_NEXT_UOFF3( p ); 1417 1418 if ( base_glyph >= gid_start && base_glyph <= gid_end ) 1419 { 1420 p1 = (FT_Byte*)( clip_base + clip_box_offset ); 1421 1422 /* Check whether we can extract one `uint8`. */ 1423 if ( p1 > limit - 1 ) 1424 return 0; 1425 1426 format = FT_NEXT_BYTE( p1 ); 1427 1428 if ( format > 2 ) 1429 return 0; 1430 1431 /* Check whether we can extract four `FWORD`. */ 1432 if ( p1 > limit - ( 2 + 2 + 2 + 2 ) ) 1433 return 0; 1434 1435 /* `face->root.size->metrics.x_scale` and `y_scale` are factors */ 1436 /* that scale a font unit value in integers to a 26.6 fixed value */ 1437 /* according to the requested size, see for example */ 1438 /* `ft_recompute_scaled_metrics`. */ 1439 font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ), 1440 face->root.size->metrics.x_scale ); 1441 font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ), 1442 face->root.size->metrics.y_scale ); 1443 font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ), 1444 face->root.size->metrics.x_scale ); 1445 font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ), 1446 face->root.size->metrics.y_scale ); 1447 1448 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1449 if ( format == 2 ) 1450 { 1451 FT_ULong var_index_base = 0; 1452 /* varIndexBase offset for clipbox is 3 at most. */ 1453 FT_ItemVarDelta item_deltas[4] = { 0, 0, 0, 0 }; 1454 1455 1456 /* Check whether we can extract a 32-bit varIndexBase now. */ 1457 if ( p1 > limit - 4 ) 1458 return 0; 1459 1460 var_index_base = FT_NEXT_ULONG( p1 ); 1461 1462 if ( !get_deltas_for_var_index_base( face, colr, var_index_base, 4, 1463 item_deltas ) ) 1464 return 0; 1465 1466 font_clip_box.xMin += 1467 FT_MulFix( item_deltas[0], face->root.size->metrics.x_scale ); 1468 font_clip_box.yMin += 1469 FT_MulFix( item_deltas[1], face->root.size->metrics.y_scale ); 1470 font_clip_box.xMax += 1471 FT_MulFix( item_deltas[2], face->root.size->metrics.x_scale ); 1472 font_clip_box.yMax += 1473 FT_MulFix( item_deltas[3], face->root.size->metrics.y_scale ); 1474 } 1475 #endif 1476 1477 /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */ 1478 /* them. If we we would only transform two corner points and */ 1479 /* span a rectangle based on those, the rectangle may become too */ 1480 /* small to cover the glyph. */ 1481 corners[0].x = font_clip_box.xMin; 1482 corners[1].x = font_clip_box.xMin; 1483 corners[2].x = font_clip_box.xMax; 1484 corners[3].x = font_clip_box.xMax; 1485 1486 corners[0].y = font_clip_box.yMin; 1487 corners[1].y = font_clip_box.yMax; 1488 corners[2].y = font_clip_box.yMax; 1489 corners[3].y = font_clip_box.yMin; 1490 1491 for ( j = 0; j < num_corners; ++j ) 1492 { 1493 if ( face->root.internal->transform_flags & 1 ) 1494 FT_Vector_Transform( &corners[j], 1495 &face->root.internal->transform_matrix ); 1496 1497 if ( face->root.internal->transform_flags & 2 ) 1498 { 1499 corners[j].x += face->root.internal->transform_delta.x; 1500 corners[j].y += face->root.internal->transform_delta.y; 1501 } 1502 } 1503 1504 clip_box->bottom_left = corners[0]; 1505 clip_box->top_left = corners[1]; 1506 clip_box->top_right = corners[2]; 1507 clip_box->bottom_right = corners[3]; 1508 1509 return 1; 1510 } 1511 } 1512 1513 return 0; 1514 } 1515 1516 1517 FT_LOCAL_DEF( FT_Bool ) tt_face_get_paint_layers(TT_Face face,FT_LayerIterator * iterator,FT_OpaquePaint * opaque_paint)1518 tt_face_get_paint_layers( TT_Face face, 1519 FT_LayerIterator* iterator, 1520 FT_OpaquePaint* opaque_paint ) 1521 { 1522 FT_Byte* p = NULL; 1523 FT_Byte* p_first_layer = NULL; 1524 FT_Byte* p_paint = NULL; 1525 FT_UInt32 paint_offset; 1526 1527 Colr* colr; 1528 1529 1530 if ( iterator->layer == iterator->num_layers ) 1531 return 0; 1532 1533 colr = (Colr*)face->colr; 1534 if ( !colr ) 1535 return 0; 1536 1537 /* 1538 * We have an iterator pointing at a paint offset as part of the 1539 * `paintOffset` array in `LayerV1List`. 1540 */ 1541 p = iterator->p; 1542 1543 /* 1544 * Do a cursor sanity check of the iterator. Counting backwards from 1545 * where it stands, we need to end up at a position after the beginning 1546 * of the `LayerV1List` table and not after the end of the 1547 * `LayerV1List`. 1548 */ 1549 p_first_layer = p - 1550 iterator->layer * LAYER_V1_LIST_PAINT_OFFSET_SIZE - 1551 LAYER_V1_LIST_NUM_LAYERS_SIZE; 1552 if ( p_first_layer < (FT_Byte*)colr->layers_v1 ) 1553 return 0; 1554 if ( p_first_layer >= (FT_Byte*)( 1555 colr->layers_v1 + LAYER_V1_LIST_NUM_LAYERS_SIZE + 1556 colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) ) 1557 return 0; 1558 1559 /* 1560 * Before reading, ensure that `p` is within 'COLR' v1 and we can read a 1561 * 4-byte ULONG. 1562 */ 1563 if ( p < colr->layers_v1 || 1564 p > (FT_Byte*)colr->table + colr->table_size - 4 ) 1565 return 0; 1566 1567 paint_offset = 1568 FT_NEXT_ULONG( p ); 1569 opaque_paint->insert_root_transform = 1570 0; 1571 1572 p_paint = (FT_Byte*)( colr->layers_v1 + paint_offset ); 1573 1574 if ( p_paint < colr->paints_start_v1 || 1575 p_paint >= ( (FT_Byte*)colr->table + colr->table_size ) ) 1576 return 0; 1577 1578 opaque_paint->p = p_paint; 1579 1580 iterator->p = p; 1581 1582 iterator->layer++; 1583 1584 return 1; 1585 } 1586 1587 1588 FT_LOCAL_DEF( FT_Bool ) tt_face_get_colorline_stops(TT_Face face,FT_ColorStop * color_stop,FT_ColorStopIterator * iterator)1589 tt_face_get_colorline_stops( TT_Face face, 1590 FT_ColorStop* color_stop, 1591 FT_ColorStopIterator *iterator ) 1592 { 1593 Colr* colr = (Colr*)face->colr; 1594 1595 FT_Byte* p; 1596 FT_ULong var_index_base; 1597 FT_Byte* last_entry_p = NULL; 1598 FT_UInt entry_size = COLOR_STOP_SIZE; 1599 1600 1601 if ( !colr || !colr->table || !iterator ) 1602 return 0; 1603 1604 if ( iterator->current_color_stop >= iterator->num_color_stops ) 1605 return 0; 1606 1607 if ( iterator->read_variable ) 1608 entry_size += VAR_IDX_BASE_SIZE; 1609 1610 /* Calculate the start pointer for the last to-be-read (Var)ColorStop */ 1611 /* and check whether we can read a full (Var)ColorStop at that */ 1612 /* position by comparing it to the position that is the size of one */ 1613 /* (Var)ColorStop before the end of the 'COLR' table. */ 1614 last_entry_p = 1615 iterator->p + ( iterator->num_color_stops - 1 - 1616 iterator->current_color_stop ) * entry_size; 1617 if ( iterator->p < colr->paints_start_v1 || 1618 last_entry_p > (FT_Byte*)colr->table + 1619 colr->table_size - entry_size ) 1620 return 0; 1621 1622 /* Iterator points at first `ColorStop` of `ColorLine`. */ 1623 p = iterator->p; 1624 1625 color_stop->stop_offset = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) ); 1626 1627 color_stop->color.palette_index = FT_NEXT_USHORT( p ); 1628 1629 color_stop->color.alpha = FT_NEXT_SHORT( p ); 1630 1631 if ( iterator->read_variable ) 1632 { 1633 /* Pointer p needs to be advanced independently of whether we intend */ 1634 /* to take variable deltas into account or not. Otherwise iteration */ 1635 /* would fail due to wrong offsets. */ 1636 var_index_base = FT_NEXT_ULONG( p ); 1637 1638 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1639 { 1640 FT_Int item_deltas[2]; 1641 1642 1643 if ( !get_deltas_for_var_index_base( face, colr, 1644 var_index_base, 1645 2, 1646 item_deltas ) ) 1647 return 0; 1648 1649 color_stop->stop_offset += F2DOT14_TO_FIXED( item_deltas[0] ); 1650 color_stop->color.alpha += (FT_F2Dot14)item_deltas[1]; 1651 } 1652 #else 1653 FT_UNUSED( var_index_base ); 1654 #endif 1655 } 1656 1657 iterator->p = p; 1658 iterator->current_color_stop++; 1659 1660 return 1; 1661 } 1662 1663 1664 FT_LOCAL_DEF( FT_Bool ) tt_face_get_paint(TT_Face face,FT_OpaquePaint opaque_paint,FT_COLR_Paint * paint)1665 tt_face_get_paint( TT_Face face, 1666 FT_OpaquePaint opaque_paint, 1667 FT_COLR_Paint* paint ) 1668 { 1669 Colr* colr = (Colr*)face->colr; 1670 FT_OpaquePaint next_paint; 1671 FT_Matrix ft_root_scale; 1672 1673 if ( !colr || !colr->base_glyphs_v1 || !colr->table ) 1674 return 0; 1675 1676 if ( opaque_paint.insert_root_transform ) 1677 { 1678 /* 'COLR' v1 glyph information is returned in unscaled coordinates, 1679 * i.e., `FT_Size` is not applied or multiplied into the values. When 1680 * client applications draw color glyphs, they can request to include 1681 * a top-level transform, which includes the active `x_scale` and 1682 * `y_scale` information for scaling the glyph, as well the additional 1683 * transform and translate configured through `FT_Set_Transform`. 1684 * This allows client applications to apply this top-level transform 1685 * to the graphics context first and only once, then have gradient and 1686 * contour scaling applied correctly when performing the additional 1687 * drawing operations for subsequenct paints. Prepare this initial 1688 * transform here. 1689 */ 1690 paint->format = FT_COLR_PAINTFORMAT_TRANSFORM; 1691 1692 next_paint.p = opaque_paint.p; 1693 next_paint.insert_root_transform = 0; 1694 paint->u.transform.paint = next_paint; 1695 1696 /* `x_scale` and `y_scale` are in 26.6 format, representing the scale 1697 * factor to get from font units to requested size. However, expected 1698 * return values are in 16.16, so we shift accordingly with rounding. 1699 */ 1700 ft_root_scale.xx = ( face->root.size->metrics.x_scale + 32 ) >> 6; 1701 ft_root_scale.xy = 0; 1702 ft_root_scale.yx = 0; 1703 ft_root_scale.yy = ( face->root.size->metrics.y_scale + 32 ) >> 6; 1704 1705 if ( face->root.internal->transform_flags & 1 ) 1706 FT_Matrix_Multiply( &face->root.internal->transform_matrix, 1707 &ft_root_scale ); 1708 1709 paint->u.transform.affine.xx = ft_root_scale.xx; 1710 paint->u.transform.affine.xy = ft_root_scale.xy; 1711 paint->u.transform.affine.yx = ft_root_scale.yx; 1712 paint->u.transform.affine.yy = ft_root_scale.yy; 1713 1714 /* The translation is specified in 26.6 format and, according to the 1715 * documentation of `FT_Set_Translate`, is performed on the character 1716 * size given in the last call to `FT_Set_Char_Size`. The 1717 * 'PaintTransform' paint table's `FT_Affine23` format expects 1718 * values in 16.16 format, thus we need to shift by 10 bits. 1719 */ 1720 if ( face->root.internal->transform_flags & 2 ) 1721 { 1722 paint->u.transform.affine.dx = 1723 face->root.internal->transform_delta.x * ( 1 << 10 ); 1724 paint->u.transform.affine.dy = 1725 face->root.internal->transform_delta.y * ( 1 << 10 ); 1726 } 1727 else 1728 { 1729 paint->u.transform.affine.dx = 0; 1730 paint->u.transform.affine.dy = 0; 1731 } 1732 1733 return 1; 1734 } 1735 1736 return read_paint( face, colr, opaque_paint.p, paint ); 1737 } 1738 1739 1740 FT_LOCAL_DEF( FT_Error ) tt_face_colr_blend_layer(TT_Face face,FT_UInt color_index,FT_GlyphSlot dstSlot,FT_GlyphSlot srcSlot)1741 tt_face_colr_blend_layer( TT_Face face, 1742 FT_UInt color_index, 1743 FT_GlyphSlot dstSlot, 1744 FT_GlyphSlot srcSlot ) 1745 { 1746 FT_Error error; 1747 1748 FT_UInt x, y; 1749 FT_Byte b, g, r, alpha; 1750 1751 FT_ULong size; 1752 FT_Byte* src; 1753 FT_Byte* dst; 1754 1755 1756 if ( !dstSlot->bitmap.buffer ) 1757 { 1758 /* Initialize destination of color bitmap */ 1759 /* with the size of first component. */ 1760 dstSlot->bitmap_left = srcSlot->bitmap_left; 1761 dstSlot->bitmap_top = srcSlot->bitmap_top; 1762 1763 dstSlot->bitmap.width = srcSlot->bitmap.width; 1764 dstSlot->bitmap.rows = srcSlot->bitmap.rows; 1765 dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA; 1766 dstSlot->bitmap.pitch = (int)dstSlot->bitmap.width * 4; 1767 dstSlot->bitmap.num_grays = 256; 1768 1769 size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch; 1770 1771 error = ft_glyphslot_alloc_bitmap( dstSlot, size ); 1772 if ( error ) 1773 return error; 1774 1775 FT_MEM_ZERO( dstSlot->bitmap.buffer, size ); 1776 } 1777 else 1778 { 1779 /* Resize destination if needed such that new component fits. */ 1780 FT_Int x_min, x_max, y_min, y_max; 1781 1782 1783 x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left ); 1784 x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width, 1785 srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width ); 1786 1787 y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows, 1788 srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows ); 1789 y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top ); 1790 1791 if ( x_min != dstSlot->bitmap_left || 1792 x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width || 1793 y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows || 1794 y_max != dstSlot->bitmap_top ) 1795 { 1796 FT_Memory memory = face->root.memory; 1797 1798 FT_UInt width = (FT_UInt)( x_max - x_min ); 1799 FT_UInt rows = (FT_UInt)( y_max - y_min ); 1800 FT_UInt pitch = width * 4; 1801 1802 FT_Byte* buf = NULL; 1803 FT_Byte* p; 1804 FT_Byte* q; 1805 1806 1807 size = rows * pitch; 1808 if ( FT_ALLOC( buf, size ) ) 1809 return error; 1810 1811 p = dstSlot->bitmap.buffer; 1812 q = buf + 1813 (int)pitch * ( y_max - dstSlot->bitmap_top ) + 1814 4 * ( dstSlot->bitmap_left - x_min ); 1815 1816 for ( y = 0; y < dstSlot->bitmap.rows; y++ ) 1817 { 1818 FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 ); 1819 1820 p += dstSlot->bitmap.pitch; 1821 q += pitch; 1822 } 1823 1824 ft_glyphslot_set_bitmap( dstSlot, buf ); 1825 1826 dstSlot->bitmap_top = y_max; 1827 dstSlot->bitmap_left = x_min; 1828 1829 dstSlot->bitmap.width = width; 1830 dstSlot->bitmap.rows = rows; 1831 dstSlot->bitmap.pitch = (int)pitch; 1832 1833 dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP; 1834 dstSlot->format = FT_GLYPH_FORMAT_BITMAP; 1835 } 1836 } 1837 1838 if ( color_index == 0xFFFF ) 1839 { 1840 if ( face->have_foreground_color ) 1841 { 1842 b = face->foreground_color.blue; 1843 g = face->foreground_color.green; 1844 r = face->foreground_color.red; 1845 alpha = face->foreground_color.alpha; 1846 } 1847 else 1848 { 1849 if ( face->palette_data.palette_flags && 1850 ( face->palette_data.palette_flags[face->palette_index] & 1851 FT_PALETTE_FOR_DARK_BACKGROUND ) ) 1852 { 1853 /* white opaque */ 1854 b = 0xFF; 1855 g = 0xFF; 1856 r = 0xFF; 1857 alpha = 0xFF; 1858 } 1859 else 1860 { 1861 /* black opaque */ 1862 b = 0x00; 1863 g = 0x00; 1864 r = 0x00; 1865 alpha = 0xFF; 1866 } 1867 } 1868 } 1869 else 1870 { 1871 b = face->palette[color_index].blue; 1872 g = face->palette[color_index].green; 1873 r = face->palette[color_index].red; 1874 alpha = face->palette[color_index].alpha; 1875 } 1876 1877 /* XXX Convert if srcSlot.bitmap is not grey? */ 1878 src = srcSlot->bitmap.buffer; 1879 dst = dstSlot->bitmap.buffer + 1880 dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) + 1881 4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left ); 1882 1883 for ( y = 0; y < srcSlot->bitmap.rows; y++ ) 1884 { 1885 for ( x = 0; x < srcSlot->bitmap.width; x++ ) 1886 { 1887 int aa = src[x]; 1888 int fa = alpha * aa / 255; 1889 1890 int fb = b * fa / 255; 1891 int fg = g * fa / 255; 1892 int fr = r * fa / 255; 1893 1894 int ba2 = 255 - fa; 1895 1896 int bb = dst[4 * x + 0]; 1897 int bg = dst[4 * x + 1]; 1898 int br = dst[4 * x + 2]; 1899 int ba = dst[4 * x + 3]; 1900 1901 1902 dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb ); 1903 dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg ); 1904 dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr ); 1905 dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa ); 1906 } 1907 1908 src += srcSlot->bitmap.pitch; 1909 dst += dstSlot->bitmap.pitch; 1910 } 1911 1912 return FT_Err_Ok; 1913 } 1914 1915 #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ 1916 1917 /* ANSI C doesn't like empty source files */ 1918 typedef int tt_colr_dummy_; 1919 1920 #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ 1921 1922 /* EOF */ 1923