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