misc/libfreetype/src/base/ftbitmap.c
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ftbitmap.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    FreeType utility functions for bitmaps (body).                       */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2004, 2005, 2006, 2007, 2008, 2009 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_BITMAP_H
       
    21 #include FT_IMAGE_H
       
    22 #include FT_INTERNAL_OBJECTS_H
       
    23 
       
    24 
       
    25   static
       
    26   const FT_Bitmap  null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
       
    27 
       
    28 
       
    29   /* documentation is in ftbitmap.h */
       
    30 
       
    31   FT_EXPORT_DEF( void )
       
    32   FT_Bitmap_New( FT_Bitmap  *abitmap )
       
    33   {
       
    34     *abitmap = null_bitmap;
       
    35   }
       
    36 
       
    37 
       
    38   /* documentation is in ftbitmap.h */
       
    39 
       
    40   FT_EXPORT_DEF( FT_Error )
       
    41   FT_Bitmap_Copy( FT_Library        library,
       
    42                   const FT_Bitmap  *source,
       
    43                   FT_Bitmap        *target)
       
    44   {
       
    45     FT_Memory  memory = library->memory;
       
    46     FT_Error   error  = FT_Err_Ok;
       
    47     FT_Int     pitch  = source->pitch;
       
    48     FT_ULong   size;
       
    49 
       
    50 
       
    51     if ( source == target )
       
    52       return FT_Err_Ok;
       
    53 
       
    54     if ( source->buffer == NULL )
       
    55     {
       
    56       *target = *source;
       
    57 
       
    58       return FT_Err_Ok;
       
    59     }
       
    60 
       
    61     if ( pitch < 0 )
       
    62       pitch = -pitch;
       
    63     size = (FT_ULong)( pitch * source->rows );
       
    64 
       
    65     if ( target->buffer )
       
    66     {
       
    67       FT_Int    target_pitch = target->pitch;
       
    68       FT_ULong  target_size;
       
    69 
       
    70 
       
    71       if ( target_pitch < 0  )
       
    72         target_pitch = -target_pitch;
       
    73       target_size = (FT_ULong)( target_pitch * target->rows );
       
    74 
       
    75       if ( target_size != size )
       
    76         (void)FT_QREALLOC( target->buffer, target_size, size );
       
    77     }
       
    78     else
       
    79       (void)FT_QALLOC( target->buffer, size );
       
    80 
       
    81     if ( !error )
       
    82     {
       
    83       unsigned char *p;
       
    84 
       
    85 
       
    86       p = target->buffer;
       
    87       *target = *source;
       
    88       target->buffer = p;
       
    89 
       
    90       FT_MEM_COPY( target->buffer, source->buffer, size );
       
    91     }
       
    92 
       
    93     return error;
       
    94   }
       
    95 
       
    96 
       
    97   static FT_Error
       
    98   ft_bitmap_assure_buffer( FT_Memory   memory,
       
    99                            FT_Bitmap*  bitmap,
       
   100                            FT_UInt     xpixels,
       
   101                            FT_UInt     ypixels )
       
   102   {
       
   103     FT_Error        error;
       
   104     int             pitch;
       
   105     int             new_pitch;
       
   106     FT_UInt         bpp;
       
   107     FT_Int          i, width, height;
       
   108     unsigned char*  buffer;
       
   109 
       
   110 
       
   111     width  = bitmap->width;
       
   112     height = bitmap->rows;
       
   113     pitch  = bitmap->pitch;
       
   114     if ( pitch < 0 )
       
   115       pitch = -pitch;
       
   116 
       
   117     switch ( bitmap->pixel_mode )
       
   118     {
       
   119     case FT_PIXEL_MODE_MONO:
       
   120       bpp       = 1;
       
   121       new_pitch = ( width + xpixels + 7 ) >> 3;
       
   122       break;
       
   123     case FT_PIXEL_MODE_GRAY2:
       
   124       bpp       = 2;
       
   125       new_pitch = ( width + xpixels + 3 ) >> 2;
       
   126       break;
       
   127     case FT_PIXEL_MODE_GRAY4:
       
   128       bpp       = 4;
       
   129       new_pitch = ( width + xpixels + 1 ) >> 1;
       
   130       break;
       
   131     case FT_PIXEL_MODE_GRAY:
       
   132     case FT_PIXEL_MODE_LCD:
       
   133     case FT_PIXEL_MODE_LCD_V:
       
   134       bpp       = 8;
       
   135       new_pitch = ( width + xpixels );
       
   136       break;
       
   137     default:
       
   138       return FT_Err_Invalid_Glyph_Format;
       
   139     }
       
   140 
       
   141     /* if no need to allocate memory */
       
   142     if ( ypixels == 0 && new_pitch <= pitch )
       
   143     {
       
   144       /* zero the padding */
       
   145       FT_Int  bit_width = pitch * 8;
       
   146       FT_Int  bit_last  = ( width + xpixels ) * bpp;
       
   147 
       
   148 
       
   149       if ( bit_last < bit_width )
       
   150       {
       
   151         FT_Byte*  line  = bitmap->buffer + ( bit_last >> 3 );
       
   152         FT_Byte*  end   = bitmap->buffer + pitch;
       
   153         FT_Int    shift = bit_last & 7;
       
   154         FT_UInt   mask  = 0xFF00U >> shift;
       
   155         FT_Int    count = height;
       
   156 
       
   157 
       
   158         for ( ; count > 0; count--, line += pitch, end += pitch )
       
   159         {
       
   160           FT_Byte*  write = line;
       
   161 
       
   162 
       
   163           if ( shift > 0 )
       
   164           {
       
   165             write[0] = (FT_Byte)( write[0] & mask );
       
   166             write++;
       
   167           }
       
   168           if ( write < end )
       
   169             FT_MEM_ZERO( write, end-write );
       
   170         }
       
   171       }
       
   172 
       
   173       return FT_Err_Ok;
       
   174     }
       
   175 
       
   176     if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
       
   177       return error;
       
   178 
       
   179     if ( bitmap->pitch > 0 )
       
   180     {
       
   181       FT_Int  len = ( width * bpp + 7 ) >> 3;
       
   182 
       
   183 
       
   184       for ( i = 0; i < bitmap->rows; i++ )
       
   185         FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
       
   186                      bitmap->buffer + pitch * i, len );
       
   187     }
       
   188     else
       
   189     {
       
   190       FT_Int  len = ( width * bpp + 7 ) >> 3;
       
   191 
       
   192 
       
   193       for ( i = 0; i < bitmap->rows; i++ )
       
   194         FT_MEM_COPY( buffer + new_pitch * i,
       
   195                      bitmap->buffer + pitch * i, len );
       
   196     }
       
   197 
       
   198     FT_FREE( bitmap->buffer );
       
   199     bitmap->buffer = buffer;
       
   200 
       
   201     if ( bitmap->pitch < 0 )
       
   202       new_pitch = -new_pitch;
       
   203 
       
   204     /* set pitch only, width and height are left untouched */
       
   205     bitmap->pitch = new_pitch;
       
   206 
       
   207     return FT_Err_Ok;
       
   208   }
       
   209 
       
   210 
       
   211   /* documentation is in ftbitmap.h */
       
   212 
       
   213   FT_EXPORT_DEF( FT_Error )
       
   214   FT_Bitmap_Embolden( FT_Library  library,
       
   215                       FT_Bitmap*  bitmap,
       
   216                       FT_Pos      xStrength,
       
   217                       FT_Pos      yStrength )
       
   218   {
       
   219     FT_Error        error;
       
   220     unsigned char*  p;
       
   221     FT_Int          i, x, y, pitch;
       
   222     FT_Int          xstr, ystr;
       
   223 
       
   224 
       
   225     if ( !library )
       
   226       return FT_Err_Invalid_Library_Handle;
       
   227 
       
   228     if ( !bitmap || !bitmap->buffer )
       
   229       return FT_Err_Invalid_Argument;
       
   230 
       
   231     if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
       
   232          ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
       
   233       return FT_Err_Invalid_Argument;
       
   234        
       
   235     xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
       
   236     ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
       
   237 
       
   238     if ( xstr == 0 && ystr == 0 )
       
   239       return FT_Err_Ok;
       
   240     else if ( xstr < 0 || ystr < 0 )
       
   241       return FT_Err_Invalid_Argument;
       
   242 
       
   243     switch ( bitmap->pixel_mode )
       
   244     {
       
   245     case FT_PIXEL_MODE_GRAY2:
       
   246     case FT_PIXEL_MODE_GRAY4:
       
   247       {
       
   248         FT_Bitmap  tmp;
       
   249         FT_Int     align;
       
   250 
       
   251 
       
   252         if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
       
   253           align = ( bitmap->width + xstr + 3 ) / 4;
       
   254         else
       
   255           align = ( bitmap->width + xstr + 1 ) / 2;
       
   256 
       
   257         FT_Bitmap_New( &tmp );
       
   258 
       
   259         error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
       
   260         if ( error )
       
   261           return error;
       
   262 
       
   263         FT_Bitmap_Done( library, bitmap );
       
   264         *bitmap = tmp;
       
   265       }
       
   266       break;
       
   267 
       
   268     case FT_PIXEL_MODE_MONO:
       
   269       if ( xstr > 8 )
       
   270         xstr = 8;
       
   271       break;
       
   272 
       
   273     case FT_PIXEL_MODE_LCD:
       
   274       xstr *= 3;
       
   275       break;
       
   276 
       
   277     case FT_PIXEL_MODE_LCD_V:
       
   278       ystr *= 3;
       
   279       break;
       
   280     }
       
   281 
       
   282     error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
       
   283     if ( error )
       
   284       return error;
       
   285 
       
   286     pitch = bitmap->pitch;
       
   287     if ( pitch > 0 )
       
   288       p = bitmap->buffer + pitch * ystr;
       
   289     else
       
   290     {
       
   291       pitch = -pitch;
       
   292       p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
       
   293     }
       
   294 
       
   295     /* for each row */
       
   296     for ( y = 0; y < bitmap->rows ; y++ )
       
   297     {
       
   298       /*
       
   299        * Horizontally:
       
   300        *
       
   301        * From the last pixel on, make each pixel or'ed with the
       
   302        * `xstr' pixels before it.
       
   303        */
       
   304       for ( x = pitch - 1; x >= 0; x-- )
       
   305       {
       
   306         unsigned char tmp;
       
   307 
       
   308 
       
   309         tmp = p[x];
       
   310         for ( i = 1; i <= xstr; i++ )
       
   311         {
       
   312           if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
       
   313           {
       
   314             p[x] |= tmp >> i;
       
   315 
       
   316             /* the maximum value of 8 for `xstr' comes from here */
       
   317             if ( x > 0 )
       
   318               p[x] |= p[x - 1] << ( 8 - i );
       
   319 
       
   320 #if 0
       
   321             if ( p[x] == 0xff )
       
   322               break;
       
   323 #endif
       
   324           }
       
   325           else
       
   326           {
       
   327             if ( x - i >= 0 )
       
   328             {
       
   329               if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
       
   330               {
       
   331                 p[x] = (unsigned char)(bitmap->num_grays - 1);
       
   332                 break;
       
   333               }
       
   334               else
       
   335               {
       
   336                 p[x] = (unsigned char)(p[x] + p[x-i]);
       
   337                 if ( p[x] == bitmap->num_grays - 1 )
       
   338                   break;
       
   339               }
       
   340             }
       
   341             else
       
   342               break;
       
   343           }
       
   344         }
       
   345       }
       
   346 
       
   347       /*
       
   348        * Vertically:
       
   349        *
       
   350        * Make the above `ystr' rows or'ed with it.
       
   351        */
       
   352       for ( x = 1; x <= ystr; x++ )
       
   353       {
       
   354         unsigned char*  q;
       
   355 
       
   356 
       
   357         q = p - bitmap->pitch * x;
       
   358         for ( i = 0; i < pitch; i++ )
       
   359           q[i] |= p[i];
       
   360       }
       
   361 
       
   362       p += bitmap->pitch;
       
   363     }
       
   364 
       
   365     bitmap->width += xstr;
       
   366     bitmap->rows += ystr;
       
   367 
       
   368     return FT_Err_Ok;
       
   369   }
       
   370 
       
   371 
       
   372   /* documentation is in ftbitmap.h */
       
   373 
       
   374   FT_EXPORT_DEF( FT_Error )
       
   375   FT_Bitmap_Convert( FT_Library        library,
       
   376                      const FT_Bitmap  *source,
       
   377                      FT_Bitmap        *target,
       
   378                      FT_Int            alignment )
       
   379   {
       
   380     FT_Error   error = FT_Err_Ok;
       
   381     FT_Memory  memory;
       
   382 
       
   383 
       
   384     if ( !library )
       
   385       return FT_Err_Invalid_Library_Handle;
       
   386 
       
   387     memory = library->memory;
       
   388 
       
   389     switch ( source->pixel_mode )
       
   390     {
       
   391     case FT_PIXEL_MODE_MONO:
       
   392     case FT_PIXEL_MODE_GRAY:
       
   393     case FT_PIXEL_MODE_GRAY2:
       
   394     case FT_PIXEL_MODE_GRAY4:
       
   395     case FT_PIXEL_MODE_LCD:
       
   396     case FT_PIXEL_MODE_LCD_V:
       
   397       {
       
   398         FT_Int   pad;
       
   399         FT_Long  old_size;
       
   400 
       
   401 
       
   402         old_size = target->rows * target->pitch;
       
   403         if ( old_size < 0 )
       
   404           old_size = -old_size;
       
   405 
       
   406         target->pixel_mode = FT_PIXEL_MODE_GRAY;
       
   407         target->rows       = source->rows;
       
   408         target->width      = source->width;
       
   409 
       
   410         pad = 0;
       
   411         if ( alignment > 0 )
       
   412         {
       
   413           pad = source->width % alignment;
       
   414           if ( pad != 0 )
       
   415             pad = alignment - pad;
       
   416         }
       
   417 
       
   418         target->pitch = source->width + pad;
       
   419 
       
   420         if ( target->rows * target->pitch > old_size             &&
       
   421              FT_QREALLOC( target->buffer,
       
   422                           old_size, target->rows * target->pitch ) )
       
   423           return error;
       
   424       }
       
   425       break;
       
   426 
       
   427     default:
       
   428       error = FT_Err_Invalid_Argument;
       
   429     }
       
   430 
       
   431     switch ( source->pixel_mode )
       
   432     {
       
   433     case FT_PIXEL_MODE_MONO:
       
   434       {
       
   435         FT_Byte*  s = source->buffer;
       
   436         FT_Byte*  t = target->buffer;
       
   437         FT_Int    i;
       
   438 
       
   439 
       
   440         target->num_grays = 2;
       
   441 
       
   442         for ( i = source->rows; i > 0; i-- )
       
   443         {
       
   444           FT_Byte*  ss = s;
       
   445           FT_Byte*  tt = t;
       
   446           FT_Int    j;
       
   447 
       
   448 
       
   449           /* get the full bytes */
       
   450           for ( j = source->width >> 3; j > 0; j-- )
       
   451           {
       
   452             FT_Int  val = ss[0]; /* avoid a byte->int cast on each line */
       
   453 
       
   454 
       
   455             tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
       
   456             tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
       
   457             tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
       
   458             tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
       
   459             tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
       
   460             tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
       
   461             tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
       
   462             tt[7] = (FT_Byte)(   val & 0x01 );
       
   463 
       
   464             tt += 8;
       
   465             ss += 1;
       
   466           }
       
   467 
       
   468           /* get remaining pixels (if any) */
       
   469           j = source->width & 7;
       
   470           if ( j > 0 )
       
   471           {
       
   472             FT_Int  val = *ss;
       
   473 
       
   474 
       
   475             for ( ; j > 0; j-- )
       
   476             {
       
   477               tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
       
   478               val <<= 1;
       
   479               tt   += 1;
       
   480             }
       
   481           }
       
   482 
       
   483           s += source->pitch;
       
   484           t += target->pitch;
       
   485         }
       
   486       }
       
   487       break;
       
   488 
       
   489 
       
   490     case FT_PIXEL_MODE_GRAY:
       
   491     case FT_PIXEL_MODE_LCD:
       
   492     case FT_PIXEL_MODE_LCD_V:
       
   493       {
       
   494         FT_Int    width   = source->width;
       
   495         FT_Byte*  s       = source->buffer;
       
   496         FT_Byte*  t       = target->buffer;
       
   497         FT_Int    s_pitch = source->pitch;
       
   498         FT_Int    t_pitch = target->pitch;
       
   499         FT_Int    i;
       
   500 
       
   501 
       
   502         target->num_grays = 256;
       
   503 
       
   504         for ( i = source->rows; i > 0; i-- )
       
   505         {
       
   506           FT_ARRAY_COPY( t, s, width );
       
   507 
       
   508           s += s_pitch;
       
   509           t += t_pitch;
       
   510         }
       
   511       }
       
   512       break;
       
   513 
       
   514 
       
   515     case FT_PIXEL_MODE_GRAY2:
       
   516       {
       
   517         FT_Byte*  s = source->buffer;
       
   518         FT_Byte*  t = target->buffer;
       
   519         FT_Int    i;
       
   520 
       
   521 
       
   522         target->num_grays = 4;
       
   523 
       
   524         for ( i = source->rows; i > 0; i-- )
       
   525         {
       
   526           FT_Byte*  ss = s;
       
   527           FT_Byte*  tt = t;
       
   528           FT_Int    j;
       
   529 
       
   530 
       
   531           /* get the full bytes */
       
   532           for ( j = source->width >> 2; j > 0; j-- )
       
   533           {
       
   534             FT_Int  val = ss[0];
       
   535 
       
   536 
       
   537             tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
       
   538             tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
       
   539             tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
       
   540             tt[3] = (FT_Byte)( ( val & 0x03 ) );
       
   541 
       
   542             ss += 1;
       
   543             tt += 4;
       
   544           }
       
   545 
       
   546           j = source->width & 3;
       
   547           if ( j > 0 )
       
   548           {
       
   549             FT_Int  val = ss[0];
       
   550 
       
   551 
       
   552             for ( ; j > 0; j-- )
       
   553             {
       
   554               tt[0]  = (FT_Byte)( ( val & 0xC0 ) >> 6 );
       
   555               val  <<= 2;
       
   556               tt    += 1;
       
   557             }
       
   558           }
       
   559 
       
   560           s += source->pitch;
       
   561           t += target->pitch;
       
   562         }
       
   563       }
       
   564       break;
       
   565 
       
   566 
       
   567     case FT_PIXEL_MODE_GRAY4:
       
   568       {
       
   569         FT_Byte*  s = source->buffer;
       
   570         FT_Byte*  t = target->buffer;
       
   571         FT_Int    i;
       
   572 
       
   573 
       
   574         target->num_grays = 16;
       
   575 
       
   576         for ( i = source->rows; i > 0; i-- )
       
   577         {
       
   578           FT_Byte*  ss = s;
       
   579           FT_Byte*  tt = t;
       
   580           FT_Int    j;
       
   581 
       
   582 
       
   583           /* get the full bytes */
       
   584           for ( j = source->width >> 1; j > 0; j-- )
       
   585           {
       
   586             FT_Int  val = ss[0];
       
   587 
       
   588 
       
   589             tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
       
   590             tt[1] = (FT_Byte)( ( val & 0x0F ) );
       
   591 
       
   592             ss += 1;
       
   593             tt += 2;
       
   594           }
       
   595 
       
   596           if ( source->width & 1 )
       
   597             tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
       
   598 
       
   599           s += source->pitch;
       
   600           t += target->pitch;
       
   601         }
       
   602       }
       
   603       break;
       
   604 
       
   605 
       
   606     default:
       
   607       ;
       
   608     }
       
   609 
       
   610     return error;
       
   611   }
       
   612 
       
   613 
       
   614   /* documentation is in ftbitmap.h */
       
   615 
       
   616   FT_EXPORT_DEF( FT_Error )
       
   617   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
       
   618   {
       
   619     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
       
   620          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
       
   621     {
       
   622       FT_Bitmap  bitmap;
       
   623       FT_Error   error;
       
   624 
       
   625 
       
   626       FT_Bitmap_New( &bitmap );
       
   627       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
       
   628       if ( error )
       
   629         return error;
       
   630 
       
   631       slot->bitmap = bitmap;
       
   632       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
       
   633     }
       
   634 
       
   635     return FT_Err_Ok;
       
   636   }
       
   637 
       
   638 
       
   639   /* documentation is in ftbitmap.h */
       
   640 
       
   641   FT_EXPORT_DEF( FT_Error )
       
   642   FT_Bitmap_Done( FT_Library  library,
       
   643                   FT_Bitmap  *bitmap )
       
   644   {
       
   645     FT_Memory  memory;
       
   646 
       
   647 
       
   648     if ( !library )
       
   649       return FT_Err_Invalid_Library_Handle;
       
   650 
       
   651     if ( !bitmap )
       
   652       return FT_Err_Invalid_Argument;
       
   653 
       
   654     memory = library->memory;
       
   655 
       
   656     FT_FREE( bitmap->buffer );
       
   657     *bitmap = null_bitmap;
       
   658 
       
   659     return FT_Err_Ok;
       
   660   }
       
   661 
       
   662 
       
   663 /* END */