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