Home | History | Annotate | Download | only in base
      1 /****************************************************************************
      2  *
      3  * ftbitmap.c
      4  *
      5  *   FreeType utility functions for bitmaps (body).
      6  *
      7  * Copyright 2004-2018 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  trace_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     FT_Vector  frac_offset;
    815 
    816     FT_Bool  free_source_bitmap          = 0;
    817     FT_Bool  free_target_bitmap_on_error = 0;
    818 
    819     FT_Pos  source_llx, source_lly, source_urx, source_ury;
    820     FT_Pos  target_llx, target_lly, target_urx, target_ury;
    821     FT_Pos  final_llx, final_lly, final_urx, final_ury;
    822 
    823     unsigned int  final_rows, final_width;
    824     long          x, y;
    825 
    826 
    827     if ( !library || !target || !source_ || !atarget_offset )
    828       return FT_THROW( Invalid_Argument );
    829 
    830     memory = library->memory;
    831 
    832     if ( !( target->pixel_mode == FT_PIXEL_MODE_NONE     ||
    833             ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
    834               target->buffer                           ) ) )
    835       return FT_THROW( Invalid_Argument );
    836 
    837     if ( source_->pixel_mode == FT_PIXEL_MODE_NONE )
    838       return FT_Err_Ok;               /* nothing to do */
    839 
    840     /* pitches must have the same sign */
    841     if ( target->pixel_mode == FT_PIXEL_MODE_BGRA &&
    842          ( source_->pitch ^ target->pitch ) < 0   )
    843       return FT_THROW( Invalid_Argument );
    844 
    845     if ( !( source_->width && source_->rows ) )
    846       return FT_Err_Ok;               /* nothing to do */
    847 
    848     /* we isolate a fractional shift of `source',        */
    849     /* to be less than one pixel and always positive;    */
    850     /* `source_offset' now holds full-pixel shift values */
    851     source_offset.x = FT_PIX_FLOOR( source_offset_.x );
    852     frac_offset.x   = source_offset_.x - source_offset.x;
    853 
    854     source_offset.y = FT_PIX_FLOOR( source_offset_.y );
    855     frac_offset.y   = source_offset_.y - source_offset.y;
    856 
    857     /* assure integer pixel offset for target bitmap */
    858     target_offset.x = FT_PIX_FLOOR( atarget_offset->x );
    859     target_offset.y = FT_PIX_FLOOR( atarget_offset->y );
    860 
    861     /* get source bitmap dimensions */
    862     source_llx = source_offset.x;
    863     if ( FT_LONG_MIN + (FT_Pos)( source_->rows << 6 ) + 64 > source_offset.y )
    864     {
    865       FT_TRACE5((
    866         "FT_Bitmap_Blend: y coordinate overflow in source bitmap\n" ));
    867       return FT_THROW( Invalid_Argument );
    868     }
    869     source_lly = source_offset.y - ( source_->rows << 6 );
    870 
    871     if ( FT_LONG_MAX - (FT_Pos)( source_->width << 6 ) - 64 < source_llx )
    872     {
    873       FT_TRACE5((
    874         "FT_Bitmap_Blend: x coordinate overflow in source bitmap\n" ));
    875       return FT_THROW( Invalid_Argument );
    876     }
    877     source_urx = source_llx + ( source_->width << 6 );
    878     source_ury = source_offset.y;
    879 
    880     /* get target bitmap dimensions */
    881     if ( target->width && target->rows )
    882     {
    883       target_llx = target_offset.x;
    884       if ( FT_LONG_MIN + (FT_Pos)( target->rows << 6 ) > target_offset.y )
    885       {
    886         FT_TRACE5((
    887           "FT_Bitmap_Blend: y coordinate overflow in target bitmap\n" ));
    888         return FT_THROW( Invalid_Argument );
    889       }
    890       target_lly = target_offset.y - ( target->rows << 6 );
    891 
    892       if ( FT_LONG_MAX - (FT_Pos)( target->width << 6 ) < target_llx )
    893       {
    894         FT_TRACE5((
    895           "FT_Bitmap_Blend: x coordinate overflow in target bitmap\n" ));
    896         return FT_THROW( Invalid_Argument );
    897       }
    898       target_urx = target_llx + ( target->width << 6 );
    899       target_ury = target_offset.y;
    900     }
    901     else
    902     {
    903       target_llx = FT_LONG_MAX;
    904       target_lly = FT_LONG_MAX;
    905       target_urx = FT_LONG_MIN;
    906       target_ury = FT_LONG_MIN;
    907     }
    908 
    909     /* move upper right corner up and to the right */
    910     /* if we have a fractional offset              */
    911     if ( source_urx >= target_urx && frac_offset.x )
    912       source_urx += 64;
    913     if ( source_ury >= target_ury && frac_offset.y )
    914       source_ury += 64;
    915 
    916     /* compute final bitmap dimensions */
    917     final_llx = FT_MIN( source_llx, target_llx );
    918     final_lly = FT_MIN( source_lly, target_lly );
    919     final_urx = FT_MAX( source_urx, target_urx );
    920     final_ury = FT_MAX( source_ury, target_ury );
    921 
    922     final_width = ( final_urx - final_llx ) >> 6;
    923     final_rows  = ( final_ury - final_lly ) >> 6;
    924 
    925 #ifdef FT_DEBUG_LEVEL_TRACE
    926     FT_TRACE5(( "FT_Bitmap_Blend:\n"
    927                 "  source bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
    928       source_llx / 64, source_lly / 64,
    929       source_urx / 64, source_ury / 64,
    930       source_->width, source_->rows ));
    931 
    932     if ( frac_offset.x || frac_offset.y )
    933       FT_TRACE5(( "    fractional offset: (%d/64, %d/64)\n",
    934                   frac_offset.x, frac_offset.y ));
    935 
    936     if ( target->width && target->rows )
    937       FT_TRACE5(( "  target bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
    938         target_llx / 64, target_lly / 64,
    939         target_urx / 64, target_ury / 64,
    940         target->width, target->rows ));
    941     else
    942       FT_TRACE5(( "  target bitmap: empty\n" ));
    943 
    944     FT_TRACE5(( "  final bitmap: (%d, %d) -- (%d, %d); %d x %d\n",
    945       final_llx / 64, final_lly / 64,
    946       final_urx / 64, final_ury / 64,
    947       final_width, final_rows ));
    948 #endif /* FT_DEBUG_LEVEL_TRACE */
    949 
    950     /* for blending, set offset vector of final bitmap */
    951     /* temporarily to (0,0)                            */
    952     source_llx -= final_llx;
    953     source_lly -= final_lly;
    954 
    955     if ( target->width && target->rows )
    956     {
    957       target_llx -= final_llx;
    958       target_lly -= final_lly;
    959     }
    960 
    961     /* set up target bitmap */
    962     if ( target->pixel_mode == FT_PIXEL_MODE_NONE )
    963     {
    964       /* create new empty bitmap */
    965       target->width      = final_width;
    966       target->rows       = final_rows;
    967       target->pixel_mode = FT_PIXEL_MODE_BGRA;
    968       target->pitch      = (int)final_width * 4;
    969       target->num_grays  = 256;
    970 
    971       if ( FT_LONG_MAX / target->pitch < (int)target->rows )
    972       {
    973         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
    974                      final_width, final_rows ));
    975         return FT_THROW( Invalid_Argument );
    976       }
    977 
    978       if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) )
    979         return error;
    980 
    981       free_target_bitmap_on_error = 1;
    982     }
    983     else if ( target->width != final_width ||
    984               target->rows  != final_rows  )
    985     {
    986       /* adjust old bitmap to enlarged size */
    987       int  pitch, new_pitch;
    988 
    989       unsigned char*  buffer = NULL;
    990 
    991 
    992       pitch = target->pitch;
    993       if ( pitch < 0 )
    994         pitch = -pitch;
    995 
    996       new_pitch = (int)final_width * 4;
    997 
    998       if ( FT_LONG_MAX / new_pitch < (int)final_rows )
    999       {
   1000         FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n",
   1001                      final_width, final_rows ));
   1002         return FT_THROW( Invalid_Argument );
   1003       }
   1004 
   1005       /* TODO: provide an in-buffer solution for large bitmaps */
   1006       /*       to avoid allocation of a new buffer             */
   1007       if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) )
   1008         goto Error;
   1009 
   1010       /* copy data to new buffer */
   1011       x = target_llx >> 6;
   1012       y = target_lly >> 6;
   1013 
   1014       /* the bitmap flow is from top to bottom, */
   1015       /* but y is measured from bottom to top   */
   1016       if ( target->pitch < 0 )
   1017       {
   1018         /* XXX */
   1019       }
   1020       else
   1021       {
   1022         unsigned char*  p =
   1023           target->buffer;
   1024         unsigned char*  q =
   1025           buffer +
   1026           ( final_rows - y - target->rows ) * new_pitch +
   1027           x * 4;
   1028         unsigned char*  limit_p =
   1029           p + pitch * (int)target->rows;
   1030 
   1031 
   1032         while ( p < limit_p )
   1033         {
   1034           FT_MEM_COPY( q, p, pitch );
   1035 
   1036           p += pitch;
   1037           q += new_pitch;
   1038         }
   1039       }
   1040 
   1041       FT_FREE( target->buffer );
   1042 
   1043       target->width = final_width;
   1044       target->rows  = final_rows;
   1045 
   1046       if ( target->pitch < 0 )
   1047         target->pitch = -new_pitch;
   1048       else
   1049         target->pitch = new_pitch;
   1050 
   1051       target->buffer = buffer;
   1052     }
   1053 
   1054     /* adjust source bitmap if necessary */
   1055     if ( source_->pixel_mode != FT_PIXEL_MODE_GRAY )
   1056     {
   1057       FT_Bitmap_Init( &source_bitmap );
   1058       error = FT_Bitmap_Convert( library, source_, &source_bitmap, 1 );
   1059       if ( error )
   1060         goto Error;
   1061 
   1062       source             = &source_bitmap;
   1063       free_source_bitmap = 1;
   1064     }
   1065     else
   1066       source = source_;
   1067 
   1068     /* do blending; the code below returns pre-multiplied channels, */
   1069     /* similar to what FreeType gets from `CBDT' tables             */
   1070     x = source_llx >> 6;
   1071     y = source_lly >> 6;
   1072 
   1073     /* XXX handle `frac_offset' */
   1074 
   1075     /* the bitmap flow is from top to bottom, */
   1076     /* but y is measured from bottom to top   */
   1077     if ( target->pitch < 0 )
   1078     {
   1079       /* XXX */
   1080     }
   1081     else
   1082     {
   1083       unsigned char*  p =
   1084         source->buffer;
   1085       unsigned char*  q =
   1086         target->buffer +
   1087         ( target->rows - y - source->rows ) * target->pitch +
   1088         x * 4;
   1089       unsigned char*  limit_p =
   1090         p + source->pitch * (int)source->rows;
   1091 
   1092 
   1093       while ( p < limit_p )
   1094       {
   1095         unsigned char*  r       = p;
   1096         unsigned char*  s       = q;
   1097         unsigned char*  limit_r = r + source->width;
   1098 
   1099 
   1100         while ( r < limit_r )
   1101         {
   1102           int  aa = *r++;
   1103           int  fa = color.alpha * aa / 255;
   1104 
   1105           int  fb = color.blue * fa / 255;
   1106           int  fg = color.green * fa / 255;
   1107           int  fr = color.red * fa / 255;
   1108 
   1109           int  ba2 = 255 - fa;
   1110 
   1111           int  bb = s[0];
   1112           int  bg = s[1];
   1113           int  br = s[2];
   1114           int  ba = s[3];
   1115 
   1116 
   1117           *s++ = (unsigned char)( bb * ba2 / 255 + fb );
   1118           *s++ = (unsigned char)( bg * ba2 / 255 + fg );
   1119           *s++ = (unsigned char)( br * ba2 / 255 + fr );
   1120           *s++ = (unsigned char)( ba * ba2 / 255 + fa );
   1121         }
   1122 
   1123         p += source->pitch;
   1124         q += target->pitch;
   1125       }
   1126     }
   1127 
   1128     atarget_offset->x = final_llx;
   1129     atarget_offset->y = final_lly + ( final_rows << 6 );
   1130 
   1131   Error:
   1132     if ( error && free_target_bitmap_on_error )
   1133       FT_Bitmap_Done( library, target );
   1134 
   1135     if ( free_source_bitmap )
   1136       FT_Bitmap_Done( library, &source_bitmap );
   1137 
   1138     return error;
   1139   }
   1140 
   1141 
   1142   /* documentation is in ftbitmap.h */
   1143 
   1144   FT_EXPORT_DEF( FT_Error )
   1145   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
   1146   {
   1147     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
   1148          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
   1149     {
   1150       FT_Bitmap  bitmap;
   1151       FT_Error   error;
   1152 
   1153 
   1154       FT_Bitmap_Init( &bitmap );
   1155       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
   1156       if ( error )
   1157         return error;
   1158 
   1159       slot->bitmap = bitmap;
   1160       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
   1161     }
   1162 
   1163     return FT_Err_Ok;
   1164   }
   1165 
   1166 
   1167   /* documentation is in ftbitmap.h */
   1168 
   1169   FT_EXPORT_DEF( FT_Error )
   1170   FT_Bitmap_Done( FT_Library  library,
   1171                   FT_Bitmap  *bitmap )
   1172   {
   1173     FT_Memory  memory;
   1174 
   1175 
   1176     if ( !library )
   1177       return FT_THROW( Invalid_Library_Handle );
   1178 
   1179     if ( !bitmap )
   1180       return FT_THROW( Invalid_Argument );
   1181 
   1182     memory = library->memory;
   1183 
   1184     FT_FREE( bitmap->buffer );
   1185     *bitmap = null_bitmap;
   1186 
   1187     return FT_Err_Ok;
   1188   }
   1189 
   1190 
   1191 /* END */
   1192