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