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