1 /****************************************************************************
   2  *
   3  * ftbitmap.c
   4  *
   5  *   FreeType utility functions for bitmaps (body).
   6  *
   7  * Copyright (C) 2004-2019 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   /**************************************************************************
  28    *
  29    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  30    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  31    * messages during execution.
  32    */
  33 #undef  FT_COMPONENT
  34 #define FT_COMPONENT  bitmap
  35 
  36 
  37   static
  38   const FT_Bitmap  null_bitmap = { 0, 0, 0, NULL, 0, 0, 0, NULL };
  39 
  40 
  41   /* documentation is in ftbitmap.h */
  42 
  43   FT_EXPORT_DEF( void )
  44   FT_Bitmap_Init( FT_Bitmap  *abitmap )
  45   {
  46     if ( abitmap )
  47       *abitmap = null_bitmap;
  48   }
  49 
  50 
  51   /* deprecated function name; retained for ABI compatibility */
  52 
  53   FT_EXPORT_DEF( void )
  54   FT_Bitmap_New( FT_Bitmap  *abitmap )
  55   {
  56     if ( abitmap )
  57       *abitmap = null_bitmap;
  58   }
  59 
  60 
  61   /* documentation is in ftbitmap.h */
  62 
  63   FT_EXPORT_DEF( FT_Error )
  64   FT_Bitmap_Copy( FT_Library        library,
  65                   const FT_Bitmap  *source,
  66                   FT_Bitmap        *target)
  67   {
  68     FT_Memory  memory;
  69     FT_Error   error  = FT_Err_Ok;
  70 
  71     FT_Int    pitch;
  72     FT_ULong  size;
  73 
  74     FT_Int  source_pitch_sign, target_pitch_sign;
  75 
  76 
  77     if ( !library )
  78       return FT_THROW( Invalid_Library_Handle );
  79 
  80     if ( !source || !target )
  81       return FT_THROW( Invalid_Argument );
  82 
  83     if ( source == target )
  84       return FT_Err_Ok;
  85 
  86     source_pitch_sign = source->pitch < 0 ? -1 : 1;
  87     target_pitch_sign = target->pitch < 0 ? -1 : 1;
  88 
  89     if ( !source->buffer )
  90     {
  91       *target = *source;
  92       if ( source_pitch_sign != target_pitch_sign )
  93         target->pitch = -target->pitch;
  94 
  95       return FT_Err_Ok;
  96     }
  97 
  98     memory = library->memory;
  99     pitch  = source->pitch;
 100 
 101     if ( pitch < 0 )
 102       pitch = -pitch;
 103     size = (FT_ULong)pitch * source->rows;
 104 
 105     if ( target->buffer )
 106     {
 107       FT_Int    target_pitch = target->pitch;
 108       FT_ULong  target_size;
 109 
 110 
 111       if ( target_pitch < 0 )
 112         target_pitch = -target_pitch;
 113       target_size = (FT_ULong)target_pitch * target->rows;
 114 
 115       if ( target_size != size )
 116         (void)FT_QREALLOC( target->buffer, target_size, size );
 117     }
 118     else
 119       (void)FT_QALLOC( target->buffer, size );
 120 
 121     if ( !error )
 122     {
 123       unsigned char *p;
 124 
 125 
 126       p = target->buffer;
 127       *target = *source;
 128       target->buffer = p;
 129 
 130       if ( source_pitch_sign == target_pitch_sign )
 131         FT_MEM_COPY( target->buffer, source->buffer, size );
 132       else
 133       {
 134         /* take care of bitmap flow */
 135         FT_UInt   i;
 136         FT_Byte*  s = source->buffer;
 137         FT_Byte*  t = target->buffer;
 138 
 139 
 140         t += (FT_ULong)pitch * ( target->rows - 1 );
 141 
 142         for ( i = target->rows; i > 0; i-- )
 143         {
 144           FT_ARRAY_COPY( t, s, pitch );
 145 
 146           s += pitch;
 147           t -= pitch;
 148         }
 149       }
 150     }
 151 
 152     return error;
 153   }
 154 
 155 
 156   /* Enlarge `bitmap' horizontally and vertically by `xpixels' */
 157   /* and `ypixels', respectively.                              */
 158 
 159   static FT_Error
 160   ft_bitmap_assure_buffer( FT_Memory   memory,
 161                            FT_Bitmap*  bitmap,
 162                            FT_UInt     xpixels,
 163                            FT_UInt     ypixels )
 164   {
 165     FT_Error        error;
 166     unsigned int    pitch;
 167     unsigned int    new_pitch;
 168     FT_UInt         bpp;
 169     FT_UInt         width, height;
 170     unsigned char*  buffer = NULL;
 171 
 172 
 173     width  = bitmap->width;
 174     height = bitmap->rows;
 175     pitch  = (unsigned int)FT_ABS( bitmap->pitch );
 176 
 177     switch ( bitmap->pixel_mode )
 178     {
 179     case FT_PIXEL_MODE_MONO:
 180       bpp       = 1;
 181       new_pitch = ( width + xpixels + 7 ) >> 3;
 182       break;
 183     case FT_PIXEL_MODE_GRAY2:
 184       bpp       = 2;
 185       new_pitch = ( width + xpixels + 3 ) >> 2;
 186       break;
 187     case FT_PIXEL_MODE_GRAY4:
 188       bpp       = 4;
 189       new_pitch = ( width + xpixels + 1 ) >> 1;
 190       break;
 191     case FT_PIXEL_MODE_GRAY:
 192     case FT_PIXEL_MODE_LCD:
 193     case FT_PIXEL_MODE_LCD_V:
 194       bpp       = 8;
 195       new_pitch = width + xpixels;
 196       break;
 197     default:
 198       return FT_THROW( Invalid_Glyph_Format );
 199     }
 200 
 201     /* if no need to allocate memory */
 202     if ( ypixels == 0 && new_pitch <= pitch )
 203     {
 204       /* zero the padding */
 205       FT_UInt  bit_width = pitch * 8;
 206       FT_UInt  bit_last  = ( width + xpixels ) * bpp;
 207 
 208 
 209       if ( bit_last < bit_width )
 210       {
 211         FT_Byte*  line  = bitmap->buffer + ( bit_last >> 3 );
 212         FT_Byte*  end   = bitmap->buffer + pitch;
 213         FT_UInt   shift = bit_last & 7;
 214         FT_UInt   mask  = 0xFF00U >> shift;
 215         FT_UInt   count = height;
 216 
 217 
 218         for ( ; count > 0; count--, line += pitch, end += pitch )
 219         {
 220           FT_Byte*  write = line;
 221 
 222 
 223           if ( shift > 0 )
 224           {
 225             write[0] = (FT_Byte)( write[0] & mask );
 226             write++;
 227           }
 228           if ( write < end )
 229             FT_MEM_ZERO( write, end - write );
 230         }
 231       }
 232 
 233       return FT_Err_Ok;
 234     }
 235 
 236     /* otherwise allocate new buffer */
 237     if ( FT_QALLOC_MULT( buffer, bitmap->rows + ypixels, new_pitch ) )
 238       return error;
 239 
 240     /* new rows get added at the top of the bitmap, */
 241     /* thus take care of the flow direction         */
 242     if ( bitmap->pitch > 0 )
 243     {
 244       FT_UInt  len = ( width * bpp + 7 ) >> 3;
 245 
 246       unsigned char*  in  = bitmap->buffer;
 247       unsigned char*  out = buffer;
 248 
 249       unsigned char*  limit = bitmap->buffer + pitch * bitmap->rows;
 250       unsigned int    delta = new_pitch - len;
 251 
 252 
 253       FT_MEM_ZERO( out, new_pitch * ypixels );
 254       out += new_pitch * ypixels;
 255 
 256       while ( in < limit )
 257       {
 258         FT_MEM_COPY( out, in, len );
 259         in  += pitch;
 260         out += len;
 261 
 262         /* we use FT_QALLOC_MULT, which doesn't zero out the buffer;      */
 263         /* consequently, we have to manually zero out the remaining bytes */
 264         FT_MEM_ZERO( out, delta );
 265         out += delta;
 266       }
 267     }
 268     else
 269     {
 270       FT_UInt  len = ( width * bpp + 7 ) >> 3;
 271 
 272       unsigned char*  in  = bitmap->buffer;
 273       unsigned char*  out = buffer;
 274 
 275       unsigned char*  limit = bitmap->buffer + pitch * bitmap->rows;
 276       unsigned int    delta = new_pitch - len;
 277 
 278 
 279       while ( in < limit )
 280       {
 281         FT_MEM_COPY( out, in, len );
 282         in  += pitch;
 283         out += len;
 284 
 285         FT_MEM_ZERO( out, delta );
 286         out += delta;
 287       }
 288 
 289       FT_MEM_ZERO( out, new_pitch * ypixels );
 290     }
 291 
 292     FT_FREE( bitmap->buffer );
 293     bitmap->buffer = buffer;
 294 
 295     /* set pitch only, width and height are left untouched */
 296     if ( bitmap->pitch < 0 )
 297       bitmap->pitch = -(int)new_pitch;
 298     else
 299       bitmap->pitch = (int)new_pitch;
 300 
 301     return FT_Err_Ok;
 302   }
 303 
 304 
 305   /* documentation is in ftbitmap.h */
 306 
 307   FT_EXPORT_DEF( FT_Error )
 308   FT_Bitmap_Embolden( FT_Library  library,
 309                       FT_Bitmap*  bitmap,
 310                       FT_Pos      xStrength,
 311                       FT_Pos      yStrength )
 312   {
 313     FT_Error        error;
 314     unsigned char*  p;
 315     FT_Int          i, x, pitch;
 316     FT_UInt         y;
 317     FT_Int          xstr, ystr;
 318 
 319 
 320     if ( !library )
 321       return FT_THROW( Invalid_Library_Handle );
 322 
 323     if ( !bitmap || !bitmap->buffer )
 324       return FT_THROW( Invalid_Argument );
 325 
 326     if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
 327          ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
 328       return FT_THROW( Invalid_Argument );
 329 
 330     xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
 331     ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
 332 
 333     if ( xstr == 0 && ystr == 0 )
 334       return FT_Err_Ok;
 335     else if ( xstr < 0 || ystr < 0 )
 336       return FT_THROW( Invalid_Argument );
 337 
 338     switch ( bitmap->pixel_mode )
 339     {
 340     case FT_PIXEL_MODE_GRAY2:
 341     case FT_PIXEL_MODE_GRAY4:
 342       {
 343         FT_Bitmap  tmp;
 344 
 345 
 346         /* convert to 8bpp */
 347         FT_Bitmap_Init( &tmp );
 348         error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 );
 349         if ( error )
 350           return error;
 351 
 352         FT_Bitmap_Done( library, bitmap );
 353         *bitmap = tmp;
 354       }
 355       break;
 356 
 357     case FT_PIXEL_MODE_MONO:
 358       if ( xstr > 8 )
 359         xstr = 8;
 360       break;
 361 
 362     case FT_PIXEL_MODE_LCD:
 363       xstr *= 3;
 364       break;
 365 
 366     case FT_PIXEL_MODE_LCD_V:
 367       ystr *= 3;
 368       break;
 369 
 370     case FT_PIXEL_MODE_BGRA:
 371       /* We don't embolden color glyphs. */
 372       return FT_Err_Ok;
 373     }
 374 
 375     error = ft_bitmap_assure_buffer( library->memory, bitmap,
 376                                      (FT_UInt)xstr, (FT_UInt)ystr );
 377     if ( error )
 378       return error;
 379 
 380     /* take care of bitmap flow */
 381     pitch = bitmap->pitch;
 382     if ( pitch > 0 )
 383       p = bitmap->buffer + pitch * ystr;
 384     else
 385     {
 386       pitch = -pitch;
 387       p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 );
 388     }
 389 
 390     /* for each row */
 391     for ( y = 0; y < bitmap->rows; y++ )
 392     {
 393       /*
 394        * Horizontally:
 395        *
 396        * From the last pixel on, make each pixel or'ed with the
 397        * `xstr' pixels before it.
 398        */
 399       for ( x = pitch - 1; x >= 0; x-- )
 400       {
 401         unsigned char  tmp;
 402 
 403 
 404         tmp = p[x];
 405         for ( i = 1; i <= xstr; i++ )
 406         {
 407           if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
 408           {
 409             p[x] |= tmp >> i;
 410 
 411             /* the maximum value of 8 for `xstr' comes from here */
 412             if ( x > 0 )
 413               p[x] |= p[x - 1] << ( 8 - i );
 414 
 415 #if 0
 416             if ( p[x] == 0xFF )
 417               break;
 418 #endif
 419           }
 420           else
 421           {
 422             if ( x - i >= 0 )
 423             {
 424               if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
 425               {
 426                 p[x] = (unsigned char)( bitmap->num_grays - 1 );
 427                 break;
 428               }
 429               else
 430               {
 431                 p[x] = (unsigned char)( p[x] + p[x - i] );
 432                 if ( p[x] == bitmap->num_grays - 1 )
 433                   break;
 434               }
 435             }
 436             else
 437               break;
 438           }
 439         }
 440       }
 441 
 442       /*
 443        * Vertically:
 444        *
 445        * Make the above `ystr' rows or'ed with it.
 446        */
 447       for ( x = 1; x <= ystr; x++ )
 448       {
 449         unsigned char*  q;
 450 
 451 
 452         q = p - bitmap->pitch * x;
 453         for ( i = 0; i < pitch; i++ )
 454           q[i] |= p[i];
 455       }
 456 
 457       p += bitmap->pitch;
 458     }
 459 
 460     bitmap->width += (FT_UInt)xstr;
 461     bitmap->rows += (FT_UInt)ystr;
 462 
 463     return FT_Err_Ok;
 464   }
 465 
 466 
 467   static FT_Byte
 468   ft_gray_for_premultiplied_srgb_bgra( const FT_Byte*  bgra )
 469   {
 470     FT_UInt  a = bgra[3];
 471     FT_UInt  l;
 472 
 473 
 474     /* Short-circuit transparent color to avoid division by zero. */
 475     if ( !a )
 476       return 0;
 477 
 478     /*
 479      * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
 480      * coefficients for RGB channels *on the linear colors*.
 481      * A gamma of 2.2 is fair to assume.  And then, we need to
 482      * undo the premultiplication too.
 483      *
 484      *   https://accessibility.kde.org/hsl-adjusted.php
 485      *
 486      * We do the computation with integers only, applying a gamma of 2.0.
 487      * We guarantee 32-bit arithmetic to avoid overflow but the resulting
 488      * luminosity fits into 16 bits.
 489      *
 490      */
 491 
 492     l = (  4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
 493           46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
 494           13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
 495 
 496     /*
 497      * Final transparency can be determined as follows.
 498      *
 499      * - If alpha is zero, we want 0.
 500      * - If alpha is zero and luminosity is zero, we want 255.
 501      * - If alpha is zero and luminosity is one, we want 0.
 502      *
 503      * So the formula is a * (1 - l) = a - l * a.
 504      *
 505      * We still need to undo premultiplication by dividing l by a*a.
 506      *
 507      */
 508 
 509     return (FT_Byte)( a - l / a );
 510   }
 511 
 512 
 513   /* documentation is in ftbitmap.h */
 514 
 515   FT_EXPORT_DEF( FT_Error )
 516   FT_Bitmap_Convert( FT_Library        library,
 517                      const FT_Bitmap  *source,
 518                      FT_Bitmap        *target,
 519                      FT_Int            alignment )
 520   {
 521     FT_Error   error = FT_Err_Ok;
 522     FT_Memory  memory;
 523 
 524     FT_Byte*  s;
 525     FT_Byte*  t;
 526 
 527 
 528     if ( !library )
 529       return FT_THROW( Invalid_Library_Handle );
 530 
 531     if ( !source || !target )
 532       return FT_THROW( Invalid_Argument );
 533 
 534     memory = library->memory;
 535 
 536     switch ( source->pixel_mode )
 537     {
 538     case FT_PIXEL_MODE_MONO:
 539     case FT_PIXEL_MODE_GRAY:
 540     case FT_PIXEL_MODE_GRAY2:
 541     case FT_PIXEL_MODE_GRAY4:
 542     case FT_PIXEL_MODE_LCD:
 543     case FT_PIXEL_MODE_LCD_V:
 544     case FT_PIXEL_MODE_BGRA:
 545       {
 546         FT_Int    pad, old_target_pitch, target_pitch;
 547         FT_ULong  old_size;
 548 
 549 
 550         old_target_pitch = target->pitch;
 551         if ( old_target_pitch < 0 )
 552           old_target_pitch = -old_target_pitch;
 553 
 554         old_size = target->rows * (FT_UInt)old_target_pitch;
 555 
 556         target->pixel_mode = FT_PIXEL_MODE_GRAY;
 557         target->rows       = source->rows;
 558         target->width      = source->width;
 559 
 560         pad = 0;
 561         if ( alignment > 0 )
 562         {
 563           pad = (FT_Int)source->width % alignment;
 564           if ( pad != 0 )
 565             pad = alignment - pad;
 566         }
 567 
 568         target_pitch = (FT_Int)source->width + pad;
 569 
 570         if ( target_pitch > 0                                               &&
 571              (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
 572           return FT_THROW( Invalid_Argument );
 573 
 574         if ( FT_QREALLOC( target->buffer,
 575                           old_size, target->rows * (FT_UInt)target_pitch ) )
 576           return error;
 577 
 578         target->pitch = target->pitch < 0 ? -target_pitch : target_pitch;
 579       }
 580       break;
 581 
 582     default:
 583       error = FT_THROW( Invalid_Argument );
 584     }
 585 
 586     s = source->buffer;
 587     t = target->buffer;
 588 
 589     /* take care of bitmap flow */
 590     if ( source->pitch < 0 )
 591       s -= source->pitch * (FT_Int)( source->rows - 1 );
 592     if ( target->pitch < 0 )
 593       t -= target->pitch * (FT_Int)( target->rows - 1 );
 594 
 595     switch ( source->pixel_mode )
 596     {
 597     case FT_PIXEL_MODE_MONO:
 598       {
 599         FT_UInt  i;
 600 
 601 
 602         target->num_grays = 2;
 603 
 604         for ( i = source->rows; i > 0; i-- )
 605         {
 606           FT_Byte*  ss = s;
 607           FT_Byte*  tt = t;
 608           FT_UInt   j;
 609 
 610 
 611           /* get the full bytes */
 612           for ( j = source->width >> 3; j > 0; j-- )
 613           {
 614             FT_Int  val = ss[0]; /* avoid a byte->int cast on each line */
 615 
 616 
 617             tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
 618             tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
 619             tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
 620             tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
 621             tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
 622             tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
 623             tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
 624             tt[7] = (FT_Byte)(   val & 0x01 );
 625 
 626             tt += 8;
 627             ss += 1;
 628           }
 629 
 630           /* get remaining pixels (if any) */
 631           j = source->width & 7;
 632           if ( j > 0 )
 633           {
 634             FT_Int  val = *ss;
 635 
 636 
 637             for ( ; j > 0; j-- )
 638             {
 639               tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
 640               val <<= 1;
 641               tt   += 1;
 642             }
 643           }
 644 
 645           s += source->pitch;
 646           t += target->pitch;
 647         }
 648       }
 649       break;
 650 
 651 
 652     case FT_PIXEL_MODE_GRAY:
 653     case FT_PIXEL_MODE_LCD:
 654     case FT_PIXEL_MODE_LCD_V:
 655       {
 656         FT_UInt  width = source->width;
 657         FT_UInt  i;
 658 
 659 
 660         target->num_grays = 256;
 661 
 662         for ( i = source->rows; i > 0; i-- )
 663         {
 664           FT_ARRAY_COPY( t, s, width );
 665 
 666           s += source->pitch;
 667           t += target->pitch;
 668         }
 669       }
 670       break;
 671 
 672 
 673     case FT_PIXEL_MODE_GRAY2:
 674       {
 675         FT_UInt  i;
 676 
 677 
 678         target->num_grays = 4;
 679 
 680         for ( i = source->rows; i > 0; i-- )
 681         {
 682           FT_Byte*  ss = s;
 683           FT_Byte*  tt = t;
 684           FT_UInt   j;
 685 
 686 
 687           /* get the full bytes */
 688           for ( j = source->width >> 2; j > 0; j-- )
 689           {
 690             FT_Int  val = ss[0];
 691 
 692 
 693             tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
 694             tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
 695             tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
 696             tt[3] = (FT_Byte)( ( val & 0x03 ) );
 697 
 698             ss += 1;
 699             tt += 4;
 700           }
 701 
 702           j = source->width & 3;
 703           if ( j > 0 )
 704           {
 705             FT_Int  val = ss[0];
 706 
 707 
 708             for ( ; j > 0; j-- )
 709             {
 710               tt[0]  = (FT_Byte)( ( val & 0xC0 ) >> 6 );
 711               val  <<= 2;
 712               tt    += 1;
 713             }
 714           }
 715 
 716           s += source->pitch;
 717           t += target->pitch;
 718         }
 719       }
 720       break;
 721 
 722 
 723     case FT_PIXEL_MODE_GRAY4:
 724       {
 725         FT_UInt  i;
 726 
 727 
 728         target->num_grays = 16;
 729 
 730         for ( i = source->rows; i > 0; i-- )
 731         {
 732           FT_Byte*  ss = s;
 733           FT_Byte*  tt = t;
 734           FT_UInt   j;
 735 
 736 
 737           /* get the full bytes */
 738           for ( j = source->width >> 1; j > 0; j-- )
 739           {
 740             FT_Int  val = ss[0];
 741 
 742 
 743             tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
 744             tt[1] = (FT_Byte)( ( val & 0x0F ) );
 745 
 746             ss += 1;
 747             tt += 2;
 748           }
 749 
 750           if ( source->width & 1 )
 751             tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
 752 
 753           s += source->pitch;
 754           t += target->pitch;
 755         }
 756       }
 757       break;
 758 
 759 
 760     case FT_PIXEL_MODE_BGRA:
 761       {
 762         FT_UInt  i;
 763 
 764 
 765         target->num_grays = 256;
 766 
 767         for ( i = source->rows; i > 0; i-- )
 768         {
 769           FT_Byte*  ss = s;
 770           FT_Byte*  tt = t;
 771           FT_UInt   j;
 772 
 773 
 774           for ( j = source->width; j > 0; j-- )
 775           {
 776             tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );
 777 
 778             ss += 4;
 779             tt += 1;
 780           }
 781 
 782           s += source->pitch;
 783           t += target->pitch;
 784         }
 785       }
 786       break;
 787 
 788     default:
 789       ;
 790     }
 791 
 792     return error;
 793   }
 794 
 795 
 796   /* documentation is in ftbitmap.h */
 797 
 798   FT_EXPORT_DEF( FT_Error )
 799   FT_Bitmap_Blend( FT_Library        library,
 800                    const FT_Bitmap*  source_,
 801                    const FT_Vector   source_offset_,
 802                    FT_Bitmap*        target,
 803                    FT_Vector        *atarget_offset,
 804                    FT_Color          color )
 805   {
 806     FT_Error   error = FT_Err_Ok;
 807     FT_Memory  memory;
 808 
 809     FT_Bitmap         source_bitmap;
 810     const FT_Bitmap*  source;
 811 
 812     FT_Vector  source_offset;
 813     FT_Vector  target_offset;
 814 
 815     FT_Bool  free_source_bitmap          = 0;
 816     FT_Bool  free_target_bitmap_on_error = 0;
 817 
 818     FT_Pos  source_llx, source_lly, source_urx, source_ury;
 819     FT_Pos  target_llx, target_lly, target_urx, target_ury;
 820     FT_Pos  final_llx, final_lly, final_urx, final_ury;
 821 
 822     unsigned int  final_rows, final_width;
 823     long          x, y;
 824 
 825 
 826     if ( !library || !target || !source_ || !atarget_offset )
 827       return FT_THROW( Invalid_Argument );
 828 
 829     memory = library->memory;
 830 
 831     if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE     ||
 832             ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
 833               target->buffer                           ) ) )
 834       return FT_THROW( Invalid_Argument );
 835 
 836     if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
 837       return FT_Err_Ok;               /* nothing to do */
 838 
 839     /* pitches must have the same sign */
 840     if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
 841          ( source_->pitch ^ target->pitch ) < 0   )
 842       return FT_THROW( Invalid_Argument );
 843 
 844     if ( !( source_->width && source_->rows ) )
 845       return FT_Err_Ok;               /* nothing to do */
 846 
 847     /* assure integer pixel offsets */
 848     source_offset.x = FT_PIX_FLOOR( source_offset_.x );
 849     source_offset.y = FT_PIX_FLOOR( source_offset_.y );
 850     target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
 851     target_offset.y = FT_PIX_FLOOR( atarget_offset->y );
 852 
 853     /* get source bitmap dimensions */
 854     source_llx = source_offset.x;
 855     if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
 856     {
 857       FT_TRACE5((
 858         "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
 859       return FT_THROW( Invalid_Argument );
 860     }
 861     source_lly = source_offset.y - ( source_->rows << 6 );
 862 
 863     if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
 864     {
 865       FT_TRACE5((
 866         "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
 867       return FT_THROW( Invalid_Argument );
 868     }
 869     source_urx = source_llx + ( source_->width << 6 );
 870     source_ury = source_offset.y;
 871 
 872     /* get target bitmap dimensions */
 873     if ( target->width && target->rows )
 874     {
 875       target_llx = target_offset.x;
 876       if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
 877       {
 878         FT_TRACE5((
 879           "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
 880         return FT_THROW( Invalid_Argument );
 881       }
 882       target_lly = target_offset.y - ( target->rows << 6 );
 883 
 884       if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
 885       {
 886         FT_TRACE5((
 887           "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
 888         return FT_THROW( Invalid_Argument );
 889       }
 890       target_urx = target_llx + ( target->width << 6 );
 891       target_ury = target_offset.y;
 892     }
 893     else
 894     {
 895       target_llx = FT_LONG_MAX;
 896       target_lly = FT_LONG_MAX;
 897       target_urx = FT_LONG_MIN;
 898       target_ury = FT_LONG_MIN;
 899     }
 900 
 901     /* compute final bitmap dimensions */
 902     final_llx = FT_MIN( source_llx, target_llx );
 903     final_lly = FT_MIN( source_lly, target_lly );
 904     final_urx = FT_MAX( source_urx, target_urx );
 905     final_ury = FT_MAX( source_ury, target_ury );
 906 
 907     final_width = ( final_urx - final_llx ) >> 6;
 908     final_rows  = ( final_ury - final_lly ) >> 6;
 909 
 910 #ifdef FT_DEBUG_LEVEL_TRACE
 911     FT_TRACE5(( "FT_Bitmap_Blend:\n"
 912                 "  source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
 913       source_llx / 64, source_lly / 64,
 914       source_urx / 64, source_ury / 64,
 915       source_->width, source_->rows ));
 916 
 917     if ( target->width && target->rows )
 918       FT_TRACE5(( "  target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
 919         target_llx / 64, target_lly / 64,
 920         target_urx / 64, target_ury / 64,
 921         target->width, target->rows ));
 922     else
 923       FT_TRACE5(( "  target bitmap: empty\n" ));
 924 
 925     FT_TRACE5(( "  final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
 926       final_llx / 64, final_lly / 64,
 927       final_urx / 64, final_ury / 64,
 928       final_width, final_rows ));
 929 #endif /* FT_DEBUG_LEVEL_TRACE */
 930 
 931     /* for blending, set offset vector of final bitmap */
 932     /* temporarily to (0,0)                            */
 933     source_llx -= final_llx;
 934     source_lly -= final_lly;
 935 
 936     if ( target->width && target->rows )
 937     {
 938       target_llx -= final_llx;
 939       target_lly -= final_lly;
 940     }
 941 
 942     /* set up target bitmap */
 943     if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
 944     {
 945       /* create new empty bitmap */
 946       target->width      = final_width;
 947       target->rows       = final_rows;
 948       target->pixel_mode = FT_PIXEL_MODE_BGRA;
 949       target->pitch      = (int)final_width * 4;
 950       target->num_grays  = 256;
 951 
 952       if ( FT_LONG_MAX / target->pitch < (int)target->rows )
 953       {
 954         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
 955                      final_width, final_rows ));
 956         return FT_THROW( Invalid_Argument );
 957       }
 958 
 959       if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
 960         return error;
 961 
 962       free_target_bitmap_on_error = 1;
 963     }
 964     else if ( target->width != final_width ||
 965               target->rows  != final_rows  )
 966     {
 967       /* adjust old bitmap to enlarged size */
 968       int  pitch, new_pitch;
 969 
 970       unsigned char*  buffer = NULL;
 971 
 972 
 973       pitch = target->pitch;
 974       if ( pitch < 0 )
 975         pitch = -pitch;
 976 
 977       new_pitch = (int)final_width * 4;
 978 
 979       if ( FT_LONG_MAX / new_pitch < (int)final_rows )
 980       {
 981         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
 982                      final_width, final_rows ));
 983         return FT_THROW( Invalid_Argument );
 984       }
 985 
 986       /* TODO: provide an in-buffer solution for large bitmaps */
 987       /*       to avoid allocation of a new buffer             */
 988       if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
 989         goto Error;
 990 
 991       /* copy data to new buffer */
 992       x = target_llx >> 6;
 993       y = target_lly >> 6;
 994 
 995       /* the bitmap flow is from top to bottom, */
 996       /* but y is measured from bottom to top   */
 997       if ( target->pitch < 0 )
 998       {
 999         /* XXX */
1000       }
1001       else
1002       {
1003         unsigned char*  p =
1004           target->buffer;
1005         unsigned char*  q =
1006           buffer +
1007           ( final_rows - y - target->rows ) * new_pitch +
1008           x * 4;
1009         unsigned char*  limit_p =
1010           p + pitch * (int)target->rows;
1011 
1012 
1013         while ( p < limit_p )
1014         {
1015           FT_MEM_COPY( q, p, pitch );
1016 
1017           p += pitch;
1018           q += new_pitch;
1019         }
1020       }
1021 
1022       FT_FREE( target->buffer );
1023 
1024       target->width = final_width;
1025       target->rows  = final_rows;
1026 
1027       if ( target->pitch < 0 )
1028         target->pitch = -new_pitch;
1029       else
1030         target->pitch = new_pitch;
1031 
1032       target->buffer = buffer;
1033     }
1034 
1035     /* adjust source bitmap if necessary */
1036     if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
1037     {
1038       FT_Bitmap_Init( &source_bitmap );
1039       error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
1040       if ( error )
1041         goto Error;
1042 
1043       source             = &source_bitmap;
1044       free_source_bitmap = 1;
1045     }
1046     else
1047       source = source_;
1048 
1049     /* do blending; the code below returns pre-multiplied channels, */
1050     /* similar to what FreeType gets from `CBDT' tables             */
1051     x = source_llx >> 6;
1052     y = source_lly >> 6;
1053 
1054     /* the bitmap flow is from top to bottom, */
1055     /* but y is measured from bottom to top   */
1056     if ( target->pitch < 0 )
1057     {
1058       /* XXX */
1059     }
1060     else
1061     {
1062       unsigned char*  p =
1063         source->buffer;
1064       unsigned char*  q =
1065         target->buffer +
1066         ( target->rows - y - source->rows ) * target->pitch +
1067         x * 4;
1068       unsigned char*  limit_p =
1069         p + source->pitch * (int)source->rows;
1070 
1071 
1072       while ( p < limit_p )
1073       {
1074         unsigned char*  r       = p;
1075         unsigned char*  s       = q;
1076         unsigned char*  limit_r = r + source->width;
1077 
1078 
1079         while ( r < limit_r )
1080         {
1081           int  aa = *r++;
1082           int  fa = color.alpha * aa / 255;
1083 
1084           int  fb = color.blue * fa / 255;
1085           int  fg = color.green * fa / 255;
1086           int  fr = color.red * fa / 255;
1087 
1088           int  ba2 = 255 - fa;
1089 
1090           int  bb = s[0];
1091           int  bg = s[1];
1092           int  br = s[2];
1093           int  ba = s[3];
1094 
1095 
1096           *s++ = (unsigned char)( bb * ba2 / 255 + fb );
1097           *s++ = (unsigned char)( bg * ba2 / 255 + fg );
1098           *s++ = (unsigned char)( br * ba2 / 255 + fr );
1099           *s++ = (unsigned char)( ba * ba2 / 255 + fa );
1100         }
1101 
1102         p += source->pitch;
1103         q += target->pitch;
1104       }
1105     }
1106 
1107     atarget_offset->x = final_llx;
1108     atarget_offset->y = final_lly + ( final_rows << 6 );
1109 
1110   Error:
1111     if ( error && free_target_bitmap_on_error )
1112       FT_Bitmap_Done( library, target );
1113 
1114     if ( free_source_bitmap )
1115       FT_Bitmap_Done( library, &source_bitmap );
1116 
1117     return error;
1118   }
1119 
1120 
1121   /* documentation is in ftbitmap.h */
1122 
1123   FT_EXPORT_DEF( FT_Error )
1124   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
1125   {
1126     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
1127          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
1128     {
1129       FT_Bitmap  bitmap;
1130       FT_Error   error;
1131 
1132 
1133       FT_Bitmap_Init( &bitmap );
1134       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
1135       if ( error )
1136         return error;
1137 
1138       slot->bitmap = bitmap;
1139       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
1140     }
1141 
1142     return FT_Err_Ok;
1143   }
1144 
1145 
1146   /* documentation is in ftbitmap.h */
1147 
1148   FT_EXPORT_DEF( FT_Error )
1149   FT_Bitmap_Done( FT_Library  library,
1150                   FT_Bitmap  *bitmap )
1151   {
1152     FT_Memory  memory;
1153 
1154 
1155     if ( !library )
1156       return FT_THROW( Invalid_Library_Handle );
1157 
1158     if ( !bitmap )
1159       return FT_THROW( Invalid_Argument );
1160 
1161     memory = library->memory;
1162 
1163     FT_FREE( bitmap->buffer );
1164     *bitmap = null_bitmap;
1165 
1166     return FT_Err_Ok;
1167   }
1168 
1169 
1170 /* END */