ftbitmap.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftbitmap.c                                                             */
00004 /*                                                                         */
00005 /*    FreeType utility functions for bitmaps (body).                       */
00006 /*                                                                         */
00007 /*  Copyright 2004, 2005, 2006, 2007, 2008, 2009 by                        */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_BITMAP_H
00021 #include FT_IMAGE_H
00022 #include FT_INTERNAL_OBJECTS_H
00023 
00024 
00025   static
00026   const FT_Bitmap  null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 };
00027 
00028 
00029   /* documentation is in ftbitmap.h */
00030 
00031   FT_EXPORT_DEF( void )
00032   FT_Bitmap_New( FT_Bitmap  *abitmap )
00033   {
00034     *abitmap = null_bitmap;
00035   }
00036 
00037 
00038   /* documentation is in ftbitmap.h */
00039 
00040   FT_EXPORT_DEF( FT_Error )
00041   FT_Bitmap_Copy( FT_Library        library,
00042                   const FT_Bitmap  *source,
00043                   FT_Bitmap        *target)
00044   {
00045     FT_Memory  memory = library->memory;
00046     FT_Error   error  = FT_Err_Ok;
00047     FT_Int     pitch  = source->pitch;
00048     FT_ULong   size;
00049 
00050 
00051     if ( source == target )
00052       return FT_Err_Ok;
00053 
00054     if ( source->buffer == NULL )
00055     {
00056       *target = *source;
00057 
00058       return FT_Err_Ok;
00059     }
00060 
00061     if ( pitch < 0 )
00062       pitch = -pitch;
00063     size = (FT_ULong)( pitch * source->rows );
00064 
00065     if ( target->buffer )
00066     {
00067       FT_Int    target_pitch = target->pitch;
00068       FT_ULong  target_size;
00069 
00070 
00071       if ( target_pitch < 0  )
00072         target_pitch = -target_pitch;
00073       target_size = (FT_ULong)( target_pitch * target->rows );
00074 
00075       if ( target_size != size )
00076         (void)FT_QREALLOC( target->buffer, target_size, size );
00077     }
00078     else
00079       (void)FT_QALLOC( target->buffer, size );
00080 
00081     if ( !error )
00082     {
00083       unsigned char *p;
00084 
00085 
00086       p = target->buffer;
00087       *target = *source;
00088       target->buffer = p;
00089 
00090       FT_MEM_COPY( target->buffer, source->buffer, size );
00091     }
00092 
00093     return error;
00094   }
00095 
00096 
00097   static FT_Error
00098   ft_bitmap_assure_buffer( FT_Memory   memory,
00099                            FT_Bitmap*  bitmap,
00100                            FT_UInt     xpixels,
00101                            FT_UInt     ypixels )
00102   {
00103     FT_Error        error;
00104     int             pitch;
00105     int             new_pitch;
00106     FT_UInt         bpp;
00107     FT_Int          i, width, height;
00108     unsigned char*  buffer;
00109 
00110 
00111     width  = bitmap->width;
00112     height = bitmap->rows;
00113     pitch  = bitmap->pitch;
00114     if ( pitch < 0 )
00115       pitch = -pitch;
00116 
00117     switch ( bitmap->pixel_mode )
00118     {
00119     case FT_PIXEL_MODE_MONO:
00120       bpp       = 1;
00121       new_pitch = ( width + xpixels + 7 ) >> 3;
00122       break;
00123     case FT_PIXEL_MODE_GRAY2:
00124       bpp       = 2;
00125       new_pitch = ( width + xpixels + 3 ) >> 2;
00126       break;
00127     case FT_PIXEL_MODE_GRAY4:
00128       bpp       = 4;
00129       new_pitch = ( width + xpixels + 1 ) >> 1;
00130       break;
00131     case FT_PIXEL_MODE_GRAY:
00132     case FT_PIXEL_MODE_LCD:
00133     case FT_PIXEL_MODE_LCD_V:
00134       bpp       = 8;
00135       new_pitch = ( width + xpixels );
00136       break;
00137     default:
00138       return FT_Err_Invalid_Glyph_Format;
00139     }
00140 
00141     /* if no need to allocate memory */
00142     if ( ypixels == 0 && new_pitch <= pitch )
00143     {
00144       /* zero the padding */
00145       FT_Int  bit_width = pitch * 8;
00146       FT_Int  bit_last  = ( width + xpixels ) * bpp;
00147 
00148 
00149       if ( bit_last < bit_width )
00150       {
00151         FT_Byte*  line  = bitmap->buffer + ( bit_last >> 3 );
00152         FT_Byte*  end   = bitmap->buffer + pitch;
00153         FT_Int    shift = bit_last & 7;
00154         FT_UInt   mask  = 0xFF00U >> shift;
00155         FT_Int    count = height;
00156 
00157 
00158         for ( ; count > 0; count--, line += pitch, end += pitch )
00159         {
00160           FT_Byte*  write = line;
00161 
00162 
00163           if ( shift > 0 )
00164           {
00165             write[0] = (FT_Byte)( write[0] & mask );
00166             write++;
00167           }
00168           if ( write < end )
00169             FT_MEM_ZERO( write, end-write );
00170         }
00171       }
00172 
00173       return FT_Err_Ok;
00174     }
00175 
00176     if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
00177       return error;
00178 
00179     if ( bitmap->pitch > 0 )
00180     {
00181       FT_Int  len = ( width * bpp + 7 ) >> 3;
00182 
00183 
00184       for ( i = 0; i < bitmap->rows; i++ )
00185         FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
00186                      bitmap->buffer + pitch * i, len );
00187     }
00188     else
00189     {
00190       FT_Int  len = ( width * bpp + 7 ) >> 3;
00191 
00192 
00193       for ( i = 0; i < bitmap->rows; i++ )
00194         FT_MEM_COPY( buffer + new_pitch * i,
00195                      bitmap->buffer + pitch * i, len );
00196     }
00197 
00198     FT_FREE( bitmap->buffer );
00199     bitmap->buffer = buffer;
00200 
00201     if ( bitmap->pitch < 0 )
00202       new_pitch = -new_pitch;
00203 
00204     /* set pitch only, width and height are left untouched */
00205     bitmap->pitch = new_pitch;
00206 
00207     return FT_Err_Ok;
00208   }
00209 
00210 
00211   /* documentation is in ftbitmap.h */
00212 
00213   FT_EXPORT_DEF( FT_Error )
00214   FT_Bitmap_Embolden( FT_Library  library,
00215                       FT_Bitmap*  bitmap,
00216                       FT_Pos      xStrength,
00217                       FT_Pos      yStrength )
00218   {
00219     FT_Error        error;
00220     unsigned char*  p;
00221     FT_Int          i, x, y, pitch;
00222     FT_Int          xstr, ystr;
00223 
00224 
00225     if ( !library )
00226       return FT_Err_Invalid_Library_Handle;
00227 
00228     if ( !bitmap || !bitmap->buffer )
00229       return FT_Err_Invalid_Argument;
00230 
00231     if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
00232          ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
00233       return FT_Err_Invalid_Argument;
00234        
00235     xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
00236     ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
00237 
00238     if ( xstr == 0 && ystr == 0 )
00239       return FT_Err_Ok;
00240     else if ( xstr < 0 || ystr < 0 )
00241       return FT_Err_Invalid_Argument;
00242 
00243     switch ( bitmap->pixel_mode )
00244     {
00245     case FT_PIXEL_MODE_GRAY2:
00246     case FT_PIXEL_MODE_GRAY4:
00247       {
00248         FT_Bitmap  tmp;
00249         FT_Int     align;
00250 
00251 
00252         if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
00253           align = ( bitmap->width + xstr + 3 ) / 4;
00254         else
00255           align = ( bitmap->width + xstr + 1 ) / 2;
00256 
00257         FT_Bitmap_New( &tmp );
00258 
00259         error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
00260         if ( error )
00261           return error;
00262 
00263         FT_Bitmap_Done( library, bitmap );
00264         *bitmap = tmp;
00265       }
00266       break;
00267 
00268     case FT_PIXEL_MODE_MONO:
00269       if ( xstr > 8 )
00270         xstr = 8;
00271       break;
00272 
00273     case FT_PIXEL_MODE_LCD:
00274       xstr *= 3;
00275       break;
00276 
00277     case FT_PIXEL_MODE_LCD_V:
00278       ystr *= 3;
00279       break;
00280     }
00281 
00282     error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
00283     if ( error )
00284       return error;
00285 
00286     pitch = bitmap->pitch;
00287     if ( pitch > 0 )
00288       p = bitmap->buffer + pitch * ystr;
00289     else
00290     {
00291       pitch = -pitch;
00292       p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
00293     }
00294 
00295     /* for each row */
00296     for ( y = 0; y < bitmap->rows ; y++ )
00297     {
00298       /*
00299        * Horizontally:
00300        *
00301        * From the last pixel on, make each pixel or'ed with the
00302        * `xstr' pixels before it.
00303        */
00304       for ( x = pitch - 1; x >= 0; x-- )
00305       {
00306         unsigned char tmp;
00307 
00308 
00309         tmp = p[x];
00310         for ( i = 1; i <= xstr; i++ )
00311         {
00312           if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO )
00313           {
00314             p[x] |= tmp >> i;
00315 
00316             /* the maximum value of 8 for `xstr' comes from here */
00317             if ( x > 0 )
00318               p[x] |= p[x - 1] << ( 8 - i );
00319 
00320 #if 0
00321             if ( p[x] == 0xff )
00322               break;
00323 #endif
00324           }
00325           else
00326           {
00327             if ( x - i >= 0 )
00328             {
00329               if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
00330               {
00331                 p[x] = (unsigned char)(bitmap->num_grays - 1);
00332                 break;
00333               }
00334               else
00335               {
00336                 p[x] = (unsigned char)(p[x] + p[x-i]);
00337                 if ( p[x] == bitmap->num_grays - 1 )
00338                   break;
00339               }
00340             }
00341             else
00342               break;
00343           }
00344         }
00345       }
00346 
00347       /*
00348        * Vertically:
00349        *
00350        * Make the above `ystr' rows or'ed with it.
00351        */
00352       for ( x = 1; x <= ystr; x++ )
00353       {
00354         unsigned char*  q;
00355 
00356 
00357         q = p - bitmap->pitch * x;
00358         for ( i = 0; i < pitch; i++ )
00359           q[i] |= p[i];
00360       }
00361 
00362       p += bitmap->pitch;
00363     }
00364 
00365     bitmap->width += xstr;
00366     bitmap->rows += ystr;
00367 
00368     return FT_Err_Ok;
00369   }
00370 
00371 
00372   /* documentation is in ftbitmap.h */
00373 
00374   FT_EXPORT_DEF( FT_Error )
00375   FT_Bitmap_Convert( FT_Library        library,
00376                      const FT_Bitmap  *source,
00377                      FT_Bitmap        *target,
00378                      FT_Int            alignment )
00379   {
00380     FT_Error   error = FT_Err_Ok;
00381     FT_Memory  memory;
00382 
00383 
00384     if ( !library )
00385       return FT_Err_Invalid_Library_Handle;
00386 
00387     memory = library->memory;
00388 
00389     switch ( source->pixel_mode )
00390     {
00391     case FT_PIXEL_MODE_MONO:
00392     case FT_PIXEL_MODE_GRAY:
00393     case FT_PIXEL_MODE_GRAY2:
00394     case FT_PIXEL_MODE_GRAY4:
00395     case FT_PIXEL_MODE_LCD:
00396     case FT_PIXEL_MODE_LCD_V:
00397       {
00398         FT_Int   pad;
00399         FT_Long  old_size;
00400 
00401 
00402         old_size = target->rows * target->pitch;
00403         if ( old_size < 0 )
00404           old_size = -old_size;
00405 
00406         target->pixel_mode = FT_PIXEL_MODE_GRAY;
00407         target->rows       = source->rows;
00408         target->width      = source->width;
00409 
00410         pad = 0;
00411         if ( alignment > 0 )
00412         {
00413           pad = source->width % alignment;
00414           if ( pad != 0 )
00415             pad = alignment - pad;
00416         }
00417 
00418         target->pitch = source->width + pad;
00419 
00420         if ( target->rows * target->pitch > old_size             &&
00421              FT_QREALLOC( target->buffer,
00422                           old_size, target->rows * target->pitch ) )
00423           return error;
00424       }
00425       break;
00426 
00427     default:
00428       error = FT_Err_Invalid_Argument;
00429     }
00430 
00431     switch ( source->pixel_mode )
00432     {
00433     case FT_PIXEL_MODE_MONO:
00434       {
00435         FT_Byte*  s = source->buffer;
00436         FT_Byte*  t = target->buffer;
00437         FT_Int    i;
00438 
00439 
00440         target->num_grays = 2;
00441 
00442         for ( i = source->rows; i > 0; i-- )
00443         {
00444           FT_Byte*  ss = s;
00445           FT_Byte*  tt = t;
00446           FT_Int    j;
00447 
00448 
00449           /* get the full bytes */
00450           for ( j = source->width >> 3; j > 0; j-- )
00451           {
00452             FT_Int  val = ss[0]; /* avoid a byte->int cast on each line */
00453 
00454 
00455             tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 );
00456             tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 );
00457             tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 );
00458             tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 );
00459             tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 );
00460             tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 );
00461             tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 );
00462             tt[7] = (FT_Byte)(   val & 0x01 );
00463 
00464             tt += 8;
00465             ss += 1;
00466           }
00467 
00468           /* get remaining pixels (if any) */
00469           j = source->width & 7;
00470           if ( j > 0 )
00471           {
00472             FT_Int  val = *ss;
00473 
00474 
00475             for ( ; j > 0; j-- )
00476             {
00477               tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7);
00478               val <<= 1;
00479               tt   += 1;
00480             }
00481           }
00482 
00483           s += source->pitch;
00484           t += target->pitch;
00485         }
00486       }
00487       break;
00488 
00489 
00490     case FT_PIXEL_MODE_GRAY:
00491     case FT_PIXEL_MODE_LCD:
00492     case FT_PIXEL_MODE_LCD_V:
00493       {
00494         FT_Int    width   = source->width;
00495         FT_Byte*  s       = source->buffer;
00496         FT_Byte*  t       = target->buffer;
00497         FT_Int    s_pitch = source->pitch;
00498         FT_Int    t_pitch = target->pitch;
00499         FT_Int    i;
00500 
00501 
00502         target->num_grays = 256;
00503 
00504         for ( i = source->rows; i > 0; i-- )
00505         {
00506           FT_ARRAY_COPY( t, s, width );
00507 
00508           s += s_pitch;
00509           t += t_pitch;
00510         }
00511       }
00512       break;
00513 
00514 
00515     case FT_PIXEL_MODE_GRAY2:
00516       {
00517         FT_Byte*  s = source->buffer;
00518         FT_Byte*  t = target->buffer;
00519         FT_Int    i;
00520 
00521 
00522         target->num_grays = 4;
00523 
00524         for ( i = source->rows; i > 0; i-- )
00525         {
00526           FT_Byte*  ss = s;
00527           FT_Byte*  tt = t;
00528           FT_Int    j;
00529 
00530 
00531           /* get the full bytes */
00532           for ( j = source->width >> 2; j > 0; j-- )
00533           {
00534             FT_Int  val = ss[0];
00535 
00536 
00537             tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 );
00538             tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 );
00539             tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 );
00540             tt[3] = (FT_Byte)( ( val & 0x03 ) );
00541 
00542             ss += 1;
00543             tt += 4;
00544           }
00545 
00546           j = source->width & 3;
00547           if ( j > 0 )
00548           {
00549             FT_Int  val = ss[0];
00550 
00551 
00552             for ( ; j > 0; j-- )
00553             {
00554               tt[0]  = (FT_Byte)( ( val & 0xC0 ) >> 6 );
00555               val  <<= 2;
00556               tt    += 1;
00557             }
00558           }
00559 
00560           s += source->pitch;
00561           t += target->pitch;
00562         }
00563       }
00564       break;
00565 
00566 
00567     case FT_PIXEL_MODE_GRAY4:
00568       {
00569         FT_Byte*  s = source->buffer;
00570         FT_Byte*  t = target->buffer;
00571         FT_Int    i;
00572 
00573 
00574         target->num_grays = 16;
00575 
00576         for ( i = source->rows; i > 0; i-- )
00577         {
00578           FT_Byte*  ss = s;
00579           FT_Byte*  tt = t;
00580           FT_Int    j;
00581 
00582 
00583           /* get the full bytes */
00584           for ( j = source->width >> 1; j > 0; j-- )
00585           {
00586             FT_Int  val = ss[0];
00587 
00588 
00589             tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 );
00590             tt[1] = (FT_Byte)( ( val & 0x0F ) );
00591 
00592             ss += 1;
00593             tt += 2;
00594           }
00595 
00596           if ( source->width & 1 )
00597             tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 );
00598 
00599           s += source->pitch;
00600           t += target->pitch;
00601         }
00602       }
00603       break;
00604 
00605 
00606     default:
00607       ;
00608     }
00609 
00610     return error;
00611   }
00612 
00613 
00614   /* documentation is in ftbitmap.h */
00615 
00616   FT_EXPORT_DEF( FT_Error )
00617   FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot  slot )
00618   {
00619     if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP   &&
00620          !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
00621     {
00622       FT_Bitmap  bitmap;
00623       FT_Error   error;
00624 
00625 
00626       FT_Bitmap_New( &bitmap );
00627       error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
00628       if ( error )
00629         return error;
00630 
00631       slot->bitmap = bitmap;
00632       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
00633     }
00634 
00635     return FT_Err_Ok;
00636   }
00637 
00638 
00639   /* documentation is in ftbitmap.h */
00640 
00641   FT_EXPORT_DEF( FT_Error )
00642   FT_Bitmap_Done( FT_Library  library,
00643                   FT_Bitmap  *bitmap )
00644   {
00645     FT_Memory  memory;
00646 
00647 
00648     if ( !library )
00649       return FT_Err_Invalid_Library_Handle;
00650 
00651     if ( !bitmap )
00652       return FT_Err_Invalid_Argument;
00653 
00654     memory = library->memory;
00655 
00656     FT_FREE( bitmap->buffer );
00657     *bitmap = null_bitmap;
00658 
00659     return FT_Err_Ok;
00660   }
00661 
00662 
00663 /* END */

Generated on Tue Jul 5 14:13:42 2011 for ROOT_528-00b_version by  doxygen 1.5.1