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