1 /***************************************************************************/ 2 /* */ 3 /* ftbitmap.c */ 4 /* */ 5 /* FreeType utility functions for bitmaps (body). */ 6 /* */ 7 /* Copyright 2004-2015 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 22 #include FT_BITMAP_H 23 #include FT_IMAGE_H 24 #include FT_INTERNAL_OBJECTS_H 25 26 27 static 28 const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 }; 29 30 31 /* documentation is in ftbitmap.h */ 32 33 FT_EXPORT_DEF( void ) FT_Bitmap_Init(FT_Bitmap * abitmap)34 FT_Bitmap_Init( FT_Bitmap *abitmap ) 35 { 36 if ( abitmap ) 37 *abitmap = null_bitmap; 38 } 39 40 41 /* deprecated function name; retained for ABI compatibility */ 42 43 FT_EXPORT_DEF( void ) FT_Bitmap_New(FT_Bitmap * abitmap)44 FT_Bitmap_New( FT_Bitmap *abitmap ) 45 { 46 if ( abitmap ) 47 *abitmap = null_bitmap; 48 } 49 50 51 /* documentation is in ftbitmap.h */ 52 53 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Copy(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target)54 FT_Bitmap_Copy( FT_Library library, 55 const FT_Bitmap *source, 56 FT_Bitmap *target) 57 { 58 FT_Memory memory; 59 FT_Error error = FT_Err_Ok; 60 61 FT_Int pitch; 62 FT_ULong size; 63 64 FT_Int source_pitch_sign, target_pitch_sign; 65 66 67 if ( !library ) 68 return FT_THROW( Invalid_Library_Handle ); 69 70 if ( !source || !target ) 71 return FT_THROW( Invalid_Argument ); 72 73 if ( source == target ) 74 return FT_Err_Ok; 75 76 source_pitch_sign = source->pitch < 0 ? -1 : 1; 77 target_pitch_sign = target->pitch < 0 ? -1 : 1; 78 79 if ( source->buffer == NULL ) 80 { 81 *target = *source; 82 if ( source_pitch_sign != target_pitch_sign ) 83 target->pitch = -target->pitch; 84 85 return FT_Err_Ok; 86 } 87 88 memory = library->memory; 89 pitch = source->pitch; 90 91 if ( pitch < 0 ) 92 pitch = -pitch; 93 size = (FT_ULong)pitch * source->rows; 94 95 if ( target->buffer ) 96 { 97 FT_Int target_pitch = target->pitch; 98 FT_ULong target_size; 99 100 101 if ( target_pitch < 0 ) 102 target_pitch = -target_pitch; 103 target_size = (FT_ULong)target_pitch * target->rows; 104 105 if ( target_size != size ) 106 (void)FT_QREALLOC( target->buffer, target_size, size ); 107 } 108 else 109 (void)FT_QALLOC( target->buffer, size ); 110 111 if ( !error ) 112 { 113 unsigned char *p; 114 115 116 p = target->buffer; 117 *target = *source; 118 target->buffer = p; 119 120 if ( source_pitch_sign == target_pitch_sign ) 121 FT_MEM_COPY( target->buffer, source->buffer, size ); 122 else 123 { 124 /* take care of bitmap flow */ 125 FT_UInt i; 126 FT_Byte* s = source->buffer; 127 FT_Byte* t = target->buffer; 128 129 130 t += (FT_ULong)pitch * ( target->rows - 1 ); 131 132 for ( i = target->rows; i > 0; i-- ) 133 { 134 FT_ARRAY_COPY( t, s, pitch ); 135 136 s += pitch; 137 t -= pitch; 138 } 139 } 140 } 141 142 return error; 143 } 144 145 146 /* Enlarge `bitmap' horizontally and vertically by `xpixels' */ 147 /* and `ypixels', respectively. */ 148 149 static FT_Error ft_bitmap_assure_buffer(FT_Memory memory,FT_Bitmap * bitmap,FT_UInt xpixels,FT_UInt ypixels)150 ft_bitmap_assure_buffer( FT_Memory memory, 151 FT_Bitmap* bitmap, 152 FT_UInt xpixels, 153 FT_UInt ypixels ) 154 { 155 FT_Error error; 156 int pitch; 157 int new_pitch; 158 FT_UInt bpp; 159 FT_UInt i, width, height; 160 unsigned char* buffer = NULL; 161 162 163 width = bitmap->width; 164 height = bitmap->rows; 165 pitch = bitmap->pitch; 166 if ( pitch < 0 ) 167 pitch = -pitch; 168 169 switch ( bitmap->pixel_mode ) 170 { 171 case FT_PIXEL_MODE_MONO: 172 bpp = 1; 173 new_pitch = (int)( ( width + xpixels + 7 ) >> 3 ); 174 break; 175 case FT_PIXEL_MODE_GRAY2: 176 bpp = 2; 177 new_pitch = (int)( ( width + xpixels + 3 ) >> 2 ); 178 break; 179 case FT_PIXEL_MODE_GRAY4: 180 bpp = 4; 181 new_pitch = (int)( ( width + xpixels + 1 ) >> 1 ); 182 break; 183 case FT_PIXEL_MODE_GRAY: 184 case FT_PIXEL_MODE_LCD: 185 case FT_PIXEL_MODE_LCD_V: 186 bpp = 8; 187 new_pitch = (int)( width + xpixels ); 188 break; 189 default: 190 return FT_THROW( Invalid_Glyph_Format ); 191 } 192 193 /* if no need to allocate memory */ 194 if ( ypixels == 0 && new_pitch <= pitch ) 195 { 196 /* zero the padding */ 197 FT_UInt bit_width = (FT_UInt)pitch * 8; 198 FT_UInt bit_last = ( width + xpixels ) * bpp; 199 200 201 if ( bit_last < bit_width ) 202 { 203 FT_Byte* line = bitmap->buffer + ( bit_last >> 3 ); 204 FT_Byte* end = bitmap->buffer + pitch; 205 FT_UInt shift = bit_last & 7; 206 FT_UInt mask = 0xFF00U >> shift; 207 FT_UInt count = height; 208 209 210 for ( ; count > 0; count--, line += pitch, end += pitch ) 211 { 212 FT_Byte* write = line; 213 214 215 if ( shift > 0 ) 216 { 217 write[0] = (FT_Byte)( write[0] & mask ); 218 write++; 219 } 220 if ( write < end ) 221 FT_MEM_ZERO( write, end - write ); 222 } 223 } 224 225 return FT_Err_Ok; 226 } 227 228 /* otherwise allocate new buffer */ 229 if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) ) 230 return error; 231 232 /* new rows get added at the top of the bitmap, */ 233 /* thus take care of the flow direction */ 234 if ( bitmap->pitch > 0 ) 235 { 236 FT_UInt len = ( width * bpp + 7 ) >> 3; 237 238 239 for ( i = 0; i < bitmap->rows; i++ ) 240 FT_MEM_COPY( buffer + (FT_UInt)new_pitch * ( ypixels + i ), 241 bitmap->buffer + (FT_UInt)pitch * i, 242 len ); 243 } 244 else 245 { 246 FT_UInt len = ( width * bpp + 7 ) >> 3; 247 248 249 for ( i = 0; i < bitmap->rows; i++ ) 250 FT_MEM_COPY( buffer + (FT_UInt)new_pitch * i, 251 bitmap->buffer + (FT_UInt)pitch * i, 252 len ); 253 } 254 255 FT_FREE( bitmap->buffer ); 256 bitmap->buffer = buffer; 257 258 if ( bitmap->pitch < 0 ) 259 new_pitch = -new_pitch; 260 261 /* set pitch only, width and height are left untouched */ 262 bitmap->pitch = new_pitch; 263 264 return FT_Err_Ok; 265 } 266 267 268 /* documentation is in ftbitmap.h */ 269 270 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Embolden(FT_Library library,FT_Bitmap * bitmap,FT_Pos xStrength,FT_Pos yStrength)271 FT_Bitmap_Embolden( FT_Library library, 272 FT_Bitmap* bitmap, 273 FT_Pos xStrength, 274 FT_Pos yStrength ) 275 { 276 FT_Error error; 277 unsigned char* p; 278 FT_Int i, x, pitch; 279 FT_UInt y; 280 FT_Int xstr, ystr; 281 282 283 if ( !library ) 284 return FT_THROW( Invalid_Library_Handle ); 285 286 if ( !bitmap || !bitmap->buffer ) 287 return FT_THROW( Invalid_Argument ); 288 289 if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) || 290 ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) ) 291 return FT_THROW( Invalid_Argument ); 292 293 xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6; 294 ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6; 295 296 if ( xstr == 0 && ystr == 0 ) 297 return FT_Err_Ok; 298 else if ( xstr < 0 || ystr < 0 ) 299 return FT_THROW( Invalid_Argument ); 300 301 switch ( bitmap->pixel_mode ) 302 { 303 case FT_PIXEL_MODE_GRAY2: 304 case FT_PIXEL_MODE_GRAY4: 305 { 306 FT_Bitmap tmp; 307 308 309 /* convert to 8bpp */ 310 FT_Bitmap_Init( &tmp ); 311 error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 ); 312 if ( error ) 313 return error; 314 315 FT_Bitmap_Done( library, bitmap ); 316 *bitmap = tmp; 317 } 318 break; 319 320 case FT_PIXEL_MODE_MONO: 321 if ( xstr > 8 ) 322 xstr = 8; 323 break; 324 325 case FT_PIXEL_MODE_LCD: 326 xstr *= 3; 327 break; 328 329 case FT_PIXEL_MODE_LCD_V: 330 ystr *= 3; 331 break; 332 333 case FT_PIXEL_MODE_BGRA: 334 /* We don't embolden color glyphs. */ 335 return FT_Err_Ok; 336 } 337 338 error = ft_bitmap_assure_buffer( library->memory, bitmap, 339 (FT_UInt)xstr, (FT_UInt)ystr ); 340 if ( error ) 341 return error; 342 343 /* take care of bitmap flow */ 344 pitch = bitmap->pitch; 345 if ( pitch > 0 ) 346 p = bitmap->buffer + pitch * ystr; 347 else 348 { 349 pitch = -pitch; 350 p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 ); 351 } 352 353 /* for each row */ 354 for ( y = 0; y < bitmap->rows ; y++ ) 355 { 356 /* 357 * Horizontally: 358 * 359 * From the last pixel on, make each pixel or'ed with the 360 * `xstr' pixels before it. 361 */ 362 for ( x = pitch - 1; x >= 0; x-- ) 363 { 364 unsigned char tmp; 365 366 367 tmp = p[x]; 368 for ( i = 1; i <= xstr; i++ ) 369 { 370 if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO ) 371 { 372 p[x] |= tmp >> i; 373 374 /* the maximum value of 8 for `xstr' comes from here */ 375 if ( x > 0 ) 376 p[x] |= p[x - 1] << ( 8 - i ); 377 378 #if 0 379 if ( p[x] == 0xFF ) 380 break; 381 #endif 382 } 383 else 384 { 385 if ( x - i >= 0 ) 386 { 387 if ( p[x] + p[x - i] > bitmap->num_grays - 1 ) 388 { 389 p[x] = (unsigned char)( bitmap->num_grays - 1 ); 390 break; 391 } 392 else 393 { 394 p[x] = (unsigned char)( p[x] + p[x - i] ); 395 if ( p[x] == bitmap->num_grays - 1 ) 396 break; 397 } 398 } 399 else 400 break; 401 } 402 } 403 } 404 405 /* 406 * Vertically: 407 * 408 * Make the above `ystr' rows or'ed with it. 409 */ 410 for ( x = 1; x <= ystr; x++ ) 411 { 412 unsigned char* q; 413 414 415 q = p - bitmap->pitch * x; 416 for ( i = 0; i < pitch; i++ ) 417 q[i] |= p[i]; 418 } 419 420 p += bitmap->pitch; 421 } 422 423 bitmap->width += (FT_UInt)xstr; 424 bitmap->rows += (FT_UInt)ystr; 425 426 return FT_Err_Ok; 427 } 428 429 430 static FT_Byte ft_gray_for_premultiplied_srgb_bgra(const FT_Byte * bgra)431 ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra ) 432 { 433 FT_UInt a = bgra[3]; 434 FT_UInt l; 435 436 437 /* Short-circuit transparent color to avoid division by zero. */ 438 if ( !a ) 439 return 0; 440 441 /* 442 * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722 443 * coefficients for RGB channels *on the linear colors*. 444 * A gamma of 2.2 is fair to assume. And then, we need to 445 * undo the premultiplication too. 446 * 447 * http://accessibility.kde.org/hsl-adjusted.php 448 * 449 * We do the computation with integers only, applying a gamma of 2.0. 450 * We guarantee 32-bit arithmetic to avoid overflow but the resulting 451 * luminosity fits into 16 bits. 452 * 453 */ 454 455 l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + 456 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + 457 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; 458 459 /* 460 * Final transparency can be determined as follows. 461 * 462 * - If alpha is zero, we want 0. 463 * - If alpha is zero and luminosity is zero, we want 255. 464 * - If alpha is zero and luminosity is one, we want 0. 465 * 466 * So the formula is a * (1 - l) = a - l * a. 467 * 468 * We still need to undo premultiplication by dividing l by a*a. 469 * 470 */ 471 472 return (FT_Byte)( a - l / a ); 473 } 474 475 476 /* documentation is in ftbitmap.h */ 477 478 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Convert(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target,FT_Int alignment)479 FT_Bitmap_Convert( FT_Library library, 480 const FT_Bitmap *source, 481 FT_Bitmap *target, 482 FT_Int alignment ) 483 { 484 FT_Error error = FT_Err_Ok; 485 FT_Memory memory; 486 487 FT_Byte* s; 488 FT_Byte* t; 489 490 491 if ( !library ) 492 return FT_THROW( Invalid_Library_Handle ); 493 494 if ( !source || !target ) 495 return FT_THROW( Invalid_Argument ); 496 497 memory = library->memory; 498 499 switch ( source->pixel_mode ) 500 { 501 case FT_PIXEL_MODE_MONO: 502 case FT_PIXEL_MODE_GRAY: 503 case FT_PIXEL_MODE_GRAY2: 504 case FT_PIXEL_MODE_GRAY4: 505 case FT_PIXEL_MODE_LCD: 506 case FT_PIXEL_MODE_LCD_V: 507 case FT_PIXEL_MODE_BGRA: 508 { 509 FT_Int pad, old_target_pitch, target_pitch; 510 FT_ULong old_size; 511 512 513 old_target_pitch = target->pitch; 514 if ( old_target_pitch < 0 ) 515 old_target_pitch = -old_target_pitch; 516 517 old_size = target->rows * (FT_UInt)old_target_pitch; 518 519 target->pixel_mode = FT_PIXEL_MODE_GRAY; 520 target->rows = source->rows; 521 target->width = source->width; 522 523 pad = 0; 524 if ( alignment > 0 ) 525 { 526 pad = (FT_Int)source->width % alignment; 527 if ( pad != 0 ) 528 pad = alignment - pad; 529 } 530 531 target_pitch = (FT_Int)source->width + pad; 532 533 if ( target_pitch > 0 && 534 (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch ) 535 return FT_THROW( Invalid_Argument ); 536 537 if ( target->rows * (FT_ULong)target_pitch > old_size && 538 FT_QREALLOC( target->buffer, 539 old_size, target->rows * (FT_UInt)target_pitch ) ) 540 return error; 541 542 target->pitch = target->pitch < 0 ? -target_pitch : target_pitch; 543 } 544 break; 545 546 default: 547 error = FT_THROW( Invalid_Argument ); 548 } 549 550 s = source->buffer; 551 t = target->buffer; 552 553 /* take care of bitmap flow */ 554 if ( source->pitch < 0 ) 555 s -= source->pitch * (FT_Int)( source->rows - 1 ); 556 if ( target->pitch < 0 ) 557 t -= target->pitch * (FT_Int)( target->rows - 1 ); 558 559 switch ( source->pixel_mode ) 560 { 561 case FT_PIXEL_MODE_MONO: 562 { 563 FT_UInt i; 564 565 566 target->num_grays = 2; 567 568 for ( i = source->rows; i > 0; i-- ) 569 { 570 FT_Byte* ss = s; 571 FT_Byte* tt = t; 572 FT_UInt j; 573 574 575 /* get the full bytes */ 576 for ( j = source->width >> 3; j > 0; j-- ) 577 { 578 FT_Int val = ss[0]; /* avoid a byte->int cast on each line */ 579 580 581 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 ); 582 tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 ); 583 tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 ); 584 tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 ); 585 tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 ); 586 tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 ); 587 tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 ); 588 tt[7] = (FT_Byte)( val & 0x01 ); 589 590 tt += 8; 591 ss += 1; 592 } 593 594 /* get remaining pixels (if any) */ 595 j = source->width & 7; 596 if ( j > 0 ) 597 { 598 FT_Int val = *ss; 599 600 601 for ( ; j > 0; j-- ) 602 { 603 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7); 604 val <<= 1; 605 tt += 1; 606 } 607 } 608 609 s += source->pitch; 610 t += target->pitch; 611 } 612 } 613 break; 614 615 616 case FT_PIXEL_MODE_GRAY: 617 case FT_PIXEL_MODE_LCD: 618 case FT_PIXEL_MODE_LCD_V: 619 { 620 FT_UInt width = source->width; 621 FT_UInt i; 622 623 624 target->num_grays = 256; 625 626 for ( i = source->rows; i > 0; i-- ) 627 { 628 FT_ARRAY_COPY( t, s, width ); 629 630 s += source->pitch; 631 t += target->pitch; 632 } 633 } 634 break; 635 636 637 case FT_PIXEL_MODE_GRAY2: 638 { 639 FT_UInt i; 640 641 642 target->num_grays = 4; 643 644 for ( i = source->rows; i > 0; i-- ) 645 { 646 FT_Byte* ss = s; 647 FT_Byte* tt = t; 648 FT_UInt j; 649 650 651 /* get the full bytes */ 652 for ( j = source->width >> 2; j > 0; j-- ) 653 { 654 FT_Int val = ss[0]; 655 656 657 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); 658 tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 ); 659 tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 ); 660 tt[3] = (FT_Byte)( ( val & 0x03 ) ); 661 662 ss += 1; 663 tt += 4; 664 } 665 666 j = source->width & 3; 667 if ( j > 0 ) 668 { 669 FT_Int val = ss[0]; 670 671 672 for ( ; j > 0; j-- ) 673 { 674 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); 675 val <<= 2; 676 tt += 1; 677 } 678 } 679 680 s += source->pitch; 681 t += target->pitch; 682 } 683 } 684 break; 685 686 687 case FT_PIXEL_MODE_GRAY4: 688 { 689 FT_UInt i; 690 691 692 target->num_grays = 16; 693 694 for ( i = source->rows; i > 0; i-- ) 695 { 696 FT_Byte* ss = s; 697 FT_Byte* tt = t; 698 FT_UInt j; 699 700 701 /* get the full bytes */ 702 for ( j = source->width >> 1; j > 0; j-- ) 703 { 704 FT_Int val = ss[0]; 705 706 707 tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 ); 708 tt[1] = (FT_Byte)( ( val & 0x0F ) ); 709 710 ss += 1; 711 tt += 2; 712 } 713 714 if ( source->width & 1 ) 715 tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 ); 716 717 s += source->pitch; 718 t += target->pitch; 719 } 720 } 721 break; 722 723 724 case FT_PIXEL_MODE_BGRA: 725 { 726 FT_UInt i; 727 728 729 target->num_grays = 256; 730 731 for ( i = source->rows; i > 0; i-- ) 732 { 733 FT_Byte* ss = s; 734 FT_Byte* tt = t; 735 FT_UInt j; 736 737 738 for ( j = source->width; j > 0; j-- ) 739 { 740 tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss ); 741 742 ss += 4; 743 tt += 1; 744 } 745 746 s += source->pitch; 747 t += target->pitch; 748 } 749 } 750 break; 751 752 default: 753 ; 754 } 755 756 return error; 757 } 758 759 760 /* documentation is in ftbitmap.h */ 761 762 FT_EXPORT_DEF( FT_Error ) FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot slot)763 FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ) 764 { 765 if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP && 766 !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) 767 { 768 FT_Bitmap bitmap; 769 FT_Error error; 770 771 772 FT_Bitmap_Init( &bitmap ); 773 error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap ); 774 if ( error ) 775 return error; 776 777 slot->bitmap = bitmap; 778 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; 779 } 780 781 return FT_Err_Ok; 782 } 783 784 785 /* documentation is in ftbitmap.h */ 786 787 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Done(FT_Library library,FT_Bitmap * bitmap)788 FT_Bitmap_Done( FT_Library library, 789 FT_Bitmap *bitmap ) 790 { 791 FT_Memory memory; 792 793 794 if ( !library ) 795 return FT_THROW( Invalid_Library_Handle ); 796 797 if ( !bitmap ) 798 return FT_THROW( Invalid_Argument ); 799 800 memory = library->memory; 801 802 FT_FREE( bitmap->buffer ); 803 *bitmap = null_bitmap; 804 805 return FT_Err_Ok; 806 } 807 808 809 /* END */ 810