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 ) FT_Bitmap_New(FT_Bitmap * abitmap)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 ) FT_Bitmap_Copy(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target)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 ft_bitmap_assure_buffer(FT_Memory memory,FT_Bitmap * bitmap,FT_UInt xpixels,FT_UInt ypixels)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 ) FT_Bitmap_Embolden(FT_Library library,FT_Bitmap * bitmap,FT_Pos xStrength,FT_Pos yStrength)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 static FT_Byte ft_gray_for_premultiplied_srgb_bgra(const FT_Byte * bgra)379 ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra ) 380 { 381 FT_Byte a = bgra[3]; 382 FT_ULong l; 383 384 385 /* Short-circuit transparent color to avoid div-by-zero. */ 386 if ( !a ) 387 return 0; 388 389 /* 390 * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722 391 * coefficients for RGB channels *on the linear colors*. 392 * A gamma of 2.2 is fair to assume. And then, we need to 393 * undo the premultiplication too. 394 * 395 * http://accessibility.kde.org/hsl-adjusted.php 396 * 397 * We do the computation with integers only, applying a gamma of 2.0. 398 * The following will never overflow 32 bits; it is a scaled-up 399 * luminosity with premultiplication not yet undone. 400 * 401 */ 402 403 l = 4731UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + 404 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + 405 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2]; 406 407 /* 408 * Final transparency can be determined as follows. 409 * 410 * - If alpha is zero, we want 0. 411 * - If alpha is zero and luminosity is zero, we want 255. 412 * - If alpha is zero and luminosity is one, we want 0. 413 * 414 * So the formula is a * (1 - l) = a - l * a. 415 * 416 * In the actual code, we undo premultiplication and scale down again. 417 * 418 */ 419 420 return a - (FT_Byte)( ( l / a ) >> 16 ); 421 } 422 423 424 /* documentation is in ftbitmap.h */ 425 426 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Convert(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target,FT_Int alignment)427 FT_Bitmap_Convert( FT_Library library, 428 const FT_Bitmap *source, 429 FT_Bitmap *target, 430 FT_Int alignment ) 431 { 432 FT_Error error = FT_Err_Ok; 433 FT_Memory memory; 434 435 436 if ( !library ) 437 return FT_THROW( Invalid_Library_Handle ); 438 439 memory = library->memory; 440 441 switch ( source->pixel_mode ) 442 { 443 case FT_PIXEL_MODE_MONO: 444 case FT_PIXEL_MODE_GRAY: 445 case FT_PIXEL_MODE_GRAY2: 446 case FT_PIXEL_MODE_GRAY4: 447 case FT_PIXEL_MODE_LCD: 448 case FT_PIXEL_MODE_LCD_V: 449 case FT_PIXEL_MODE_BGRA: 450 { 451 FT_Int pad; 452 FT_Long old_size; 453 454 455 old_size = target->rows * target->pitch; 456 if ( old_size < 0 ) 457 old_size = -old_size; 458 459 target->pixel_mode = FT_PIXEL_MODE_GRAY; 460 target->rows = source->rows; 461 target->width = source->width; 462 463 pad = 0; 464 if ( alignment > 0 ) 465 { 466 pad = source->width % alignment; 467 if ( pad != 0 ) 468 pad = alignment - pad; 469 } 470 471 target->pitch = source->width + pad; 472 473 if ( target->pitch > 0 && 474 (FT_ULong)target->rows > FT_ULONG_MAX / target->pitch ) 475 return FT_THROW( Invalid_Argument ); 476 477 if ( target->rows * target->pitch > old_size && 478 FT_QREALLOC( target->buffer, 479 old_size, target->rows * target->pitch ) ) 480 return error; 481 } 482 break; 483 484 default: 485 error = FT_THROW( Invalid_Argument ); 486 } 487 488 switch ( source->pixel_mode ) 489 { 490 case FT_PIXEL_MODE_MONO: 491 { 492 FT_Byte* s = source->buffer; 493 FT_Byte* t = target->buffer; 494 FT_Int i; 495 496 497 target->num_grays = 2; 498 499 for ( i = source->rows; i > 0; i-- ) 500 { 501 FT_Byte* ss = s; 502 FT_Byte* tt = t; 503 FT_Int j; 504 505 506 /* get the full bytes */ 507 for ( j = source->width >> 3; j > 0; j-- ) 508 { 509 FT_Int val = ss[0]; /* avoid a byte->int cast on each line */ 510 511 512 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 ); 513 tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 ); 514 tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 ); 515 tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 ); 516 tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 ); 517 tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 ); 518 tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 ); 519 tt[7] = (FT_Byte)( val & 0x01 ); 520 521 tt += 8; 522 ss += 1; 523 } 524 525 /* get remaining pixels (if any) */ 526 j = source->width & 7; 527 if ( j > 0 ) 528 { 529 FT_Int val = *ss; 530 531 532 for ( ; j > 0; j-- ) 533 { 534 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7); 535 val <<= 1; 536 tt += 1; 537 } 538 } 539 540 s += source->pitch; 541 t += target->pitch; 542 } 543 } 544 break; 545 546 547 case FT_PIXEL_MODE_GRAY: 548 case FT_PIXEL_MODE_LCD: 549 case FT_PIXEL_MODE_LCD_V: 550 { 551 FT_Int width = source->width; 552 FT_Byte* s = source->buffer; 553 FT_Byte* t = target->buffer; 554 FT_Int s_pitch = source->pitch; 555 FT_Int t_pitch = target->pitch; 556 FT_Int i; 557 558 559 target->num_grays = 256; 560 561 for ( i = source->rows; i > 0; i-- ) 562 { 563 FT_ARRAY_COPY( t, s, width ); 564 565 s += s_pitch; 566 t += t_pitch; 567 } 568 } 569 break; 570 571 572 case FT_PIXEL_MODE_GRAY2: 573 { 574 FT_Byte* s = source->buffer; 575 FT_Byte* t = target->buffer; 576 FT_Int i; 577 578 579 target->num_grays = 4; 580 581 for ( i = source->rows; i > 0; i-- ) 582 { 583 FT_Byte* ss = s; 584 FT_Byte* tt = t; 585 FT_Int j; 586 587 588 /* get the full bytes */ 589 for ( j = source->width >> 2; j > 0; j-- ) 590 { 591 FT_Int val = ss[0]; 592 593 594 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); 595 tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 ); 596 tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 ); 597 tt[3] = (FT_Byte)( ( val & 0x03 ) ); 598 599 ss += 1; 600 tt += 4; 601 } 602 603 j = source->width & 3; 604 if ( j > 0 ) 605 { 606 FT_Int val = ss[0]; 607 608 609 for ( ; j > 0; j-- ) 610 { 611 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); 612 val <<= 2; 613 tt += 1; 614 } 615 } 616 617 s += source->pitch; 618 t += target->pitch; 619 } 620 } 621 break; 622 623 624 case FT_PIXEL_MODE_GRAY4: 625 { 626 FT_Byte* s = source->buffer; 627 FT_Byte* t = target->buffer; 628 FT_Int i; 629 630 631 target->num_grays = 16; 632 633 for ( i = source->rows; i > 0; i-- ) 634 { 635 FT_Byte* ss = s; 636 FT_Byte* tt = t; 637 FT_Int j; 638 639 640 /* get the full bytes */ 641 for ( j = source->width >> 1; j > 0; j-- ) 642 { 643 FT_Int val = ss[0]; 644 645 646 tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 ); 647 tt[1] = (FT_Byte)( ( val & 0x0F ) ); 648 649 ss += 1; 650 tt += 2; 651 } 652 653 if ( source->width & 1 ) 654 tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 ); 655 656 s += source->pitch; 657 t += target->pitch; 658 } 659 } 660 break; 661 662 case FT_PIXEL_MODE_BGRA: 663 { 664 FT_Byte* s = source->buffer; 665 FT_Byte* t = target->buffer; 666 FT_Int s_pitch = source->pitch; 667 FT_Int t_pitch = target->pitch; 668 FT_Int i; 669 670 671 target->num_grays = 256; 672 673 for ( i = source->rows; i > 0; i-- ) 674 { 675 FT_Byte* ss = s; 676 FT_Byte* tt = t; 677 FT_Int j; 678 679 680 for ( j = source->width; j > 0; j-- ) 681 { 682 tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss ); 683 684 ss += 4; 685 tt += 1; 686 } 687 688 s += s_pitch; 689 t += t_pitch; 690 } 691 } 692 break; 693 694 default: 695 ; 696 } 697 698 return error; 699 } 700 701 702 /* documentation is in ftbitmap.h */ 703 704 FT_EXPORT_DEF( FT_Error ) FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot slot)705 FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ) 706 { 707 if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP && 708 !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) 709 { 710 FT_Bitmap bitmap; 711 FT_Error error; 712 713 714 FT_Bitmap_New( &bitmap ); 715 error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap ); 716 if ( error ) 717 return error; 718 719 slot->bitmap = bitmap; 720 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; 721 } 722 723 return FT_Err_Ok; 724 } 725 726 727 /* documentation is in ftbitmap.h */ 728 729 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Done(FT_Library library,FT_Bitmap * bitmap)730 FT_Bitmap_Done( FT_Library library, 731 FT_Bitmap *bitmap ) 732 { 733 FT_Memory memory; 734 735 736 if ( !library ) 737 return FT_THROW( Invalid_Library_Handle ); 738 739 if ( !bitmap ) 740 return FT_THROW( Invalid_Argument ); 741 742 memory = library->memory; 743 744 FT_FREE( bitmap->buffer ); 745 *bitmap = null_bitmap; 746 747 return FT_Err_Ok; 748 } 749 750 751 /* END */ 752