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