ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

t1afm.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  t1afm.c                                                                */
00004 /*                                                                         */
00005 /*    AFM support for Type 1 fonts (body).                                 */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
00008 /*            2010 by                                                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 
00020 #include <ft2build.h>
00021 #include "t1afm.h"
00022 #include "t1errors.h"
00023 #include FT_INTERNAL_STREAM_H
00024 #include FT_INTERNAL_POSTSCRIPT_AUX_H
00025 
00026 
00027   /*************************************************************************/
00028   /*                                                                       */
00029   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00030   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00031   /* messages during execution.                                            */
00032   /*                                                                       */
00033 #undef  FT_COMPONENT
00034 #define FT_COMPONENT  trace_t1afm
00035 
00036 
00037   FT_LOCAL_DEF( void )
00038   T1_Done_Metrics( FT_Memory     memory,
00039                    AFM_FontInfo  fi )
00040   {
00041     FT_FREE( fi->KernPairs );
00042     fi->NumKernPair = 0;
00043 
00044     FT_FREE( fi->TrackKerns );
00045     fi->NumTrackKern = 0;
00046 
00047     FT_FREE( fi );
00048   }
00049 
00050 
00051   /* read a glyph name and return the equivalent glyph index */
00052   static FT_Int
00053   t1_get_index( const char*  name,
00054                 FT_Offset    len,
00055                 void*        user_data )
00056   {
00057     T1_Font  type1 = (T1_Font)user_data;
00058     FT_Int   n;
00059 
00060 
00061     /* PS string/name length must be < 16-bit */
00062     if ( len > 0xFFFFU )
00063       return 0;
00064 
00065     for ( n = 0; n < type1->num_glyphs; n++ )
00066     {
00067       char*  gname = (char*)type1->glyph_names[n];
00068 
00069 
00070       if ( gname && gname[0] == name[0]        &&
00071            ft_strlen( gname ) == len           &&
00072            ft_strncmp( gname, name, len ) == 0 )
00073         return n;
00074     }
00075 
00076     return 0;
00077   }
00078 
00079 
00080 #undef  KERN_INDEX
00081 #define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)(g1) << 16 ) | (g2) )
00082 
00083 
00084   /* compare two kerning pairs */
00085   FT_CALLBACK_DEF( int )
00086   compare_kern_pairs( const void*  a,
00087                       const void*  b )
00088   {
00089     AFM_KernPair  pair1 = (AFM_KernPair)a;
00090     AFM_KernPair  pair2 = (AFM_KernPair)b;
00091 
00092     FT_ULong  index1 = KERN_INDEX( pair1->index1, pair1->index2 );
00093     FT_ULong  index2 = KERN_INDEX( pair2->index1, pair2->index2 );
00094 
00095 
00096     if ( index1 > index2 )
00097       return 1;
00098     else if ( index1 < index2 )
00099       return -1;
00100     else
00101       return 0;
00102   }
00103 
00104 
00105   /* parse a PFM file -- for now, only read the kerning pairs */
00106   static FT_Error
00107   T1_Read_PFM( FT_Face       t1_face,
00108                FT_Stream     stream,
00109                AFM_FontInfo  fi )
00110   {
00111     FT_Error      error = T1_Err_Ok;
00112     FT_Memory     memory = stream->memory;
00113     FT_Byte*      start;
00114     FT_Byte*      limit;
00115     FT_Byte*      p;
00116     AFM_KernPair  kp;
00117     FT_Int        width_table_length;
00118     FT_CharMap    oldcharmap;
00119     FT_CharMap    charmap;
00120     FT_Int        n;
00121 
00122 
00123     start = (FT_Byte*)stream->cursor;
00124     limit = (FT_Byte*)stream->limit;
00125     p     = start;
00126 
00127     /* Figure out how long the width table is.          */
00128     /* This info is a little-endian short at offset 99. */
00129     p = start + 99;
00130     if ( p + 2 > limit )
00131     {
00132       error = T1_Err_Unknown_File_Format;
00133       goto Exit;
00134     }
00135     width_table_length = FT_PEEK_USHORT_LE( p );
00136 
00137     p += 18 + width_table_length;
00138     if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 )
00139       /* extension table is probably optional */
00140       goto Exit;
00141 
00142     /* Kerning offset is 14 bytes from start of extensions table. */
00143     p += 14;
00144     p = start + FT_PEEK_ULONG_LE( p );
00145 
00146     if ( p == start )
00147       /* zero offset means no table */
00148       goto Exit;
00149 
00150     if ( p + 2 > limit )
00151     {
00152       error = T1_Err_Unknown_File_Format;
00153       goto Exit;
00154     }
00155 
00156     fi->NumKernPair = FT_PEEK_USHORT_LE( p );
00157     p += 2;
00158     if ( p + 4 * fi->NumKernPair > limit )
00159     {
00160       error = T1_Err_Unknown_File_Format;
00161       goto Exit;
00162     }
00163 
00164     /* Actually, kerning pairs are simply optional! */
00165     if ( fi->NumKernPair == 0 )
00166       goto Exit;
00167 
00168     /* allocate the pairs */
00169     if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
00170       goto Exit;
00171 
00172     /* now, read each kern pair */
00173     kp             = fi->KernPairs;
00174     limit          = p + 4 * fi->NumKernPair;
00175 
00176     /* PFM kerning data are stored by encoding rather than glyph index, */
00177     /* so find the PostScript charmap of this font and install it       */
00178     /* temporarily.  If we find no PostScript charmap, then just use    */
00179     /* the default and hope it is the right one.                        */
00180     oldcharmap = t1_face->charmap;
00181     charmap    = NULL;
00182 
00183     for ( n = 0; n < t1_face->num_charmaps; n++ )
00184     {
00185       charmap = t1_face->charmaps[n];
00186       /* check against PostScript pseudo platform */
00187       if ( charmap->platform_id == 7 )
00188       {
00189         error = FT_Set_Charmap( t1_face, charmap );
00190         if ( error )
00191           goto Exit;
00192         break;
00193       }
00194     }
00195 
00196     /* Kerning info is stored as:             */
00197     /*                                        */
00198     /*   encoding of first glyph (1 byte)     */
00199     /*   encoding of second glyph (1 byte)    */
00200     /*   offset (little-endian short)         */
00201     for ( ; p < limit ; p += 4 )
00202     {
00203       kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
00204       kp->index2 = FT_Get_Char_Index( t1_face, p[1] );
00205 
00206       kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2);
00207       kp->y = 0;
00208 
00209       kp++;
00210     }
00211 
00212     if ( oldcharmap != NULL )
00213       error = FT_Set_Charmap( t1_face, oldcharmap );
00214     if ( error )
00215       goto Exit;
00216 
00217     /* now, sort the kern pairs according to their glyph indices */
00218     ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),
00219               compare_kern_pairs );
00220 
00221   Exit:
00222     if ( error )
00223     {
00224       FT_FREE( fi->KernPairs );
00225       fi->NumKernPair = 0;
00226     }
00227 
00228     return error;
00229   }
00230 
00231 
00232   /* parse a metrics file -- either AFM or PFM depending on what */
00233   /* it turns out to be                                          */
00234   FT_LOCAL_DEF( FT_Error )
00235   T1_Read_Metrics( FT_Face    t1_face,
00236                    FT_Stream  stream )
00237   {
00238     PSAux_Service  psaux;
00239     FT_Memory      memory  = stream->memory;
00240     AFM_ParserRec  parser;
00241     AFM_FontInfo   fi      = NULL;
00242     FT_Error       error   = T1_Err_Unknown_File_Format;
00243     T1_Font        t1_font = &( (T1_Face)t1_face )->type1;
00244 
00245 
00246     if ( FT_NEW( fi )                   ||
00247          FT_FRAME_ENTER( stream->size ) )
00248       goto Exit;
00249 
00250     fi->FontBBox  = t1_font->font_bbox;
00251     fi->Ascender  = t1_font->font_bbox.yMax;
00252     fi->Descender = t1_font->font_bbox.yMin;
00253 
00254     psaux = (PSAux_Service)( (T1_Face)t1_face )->psaux;
00255     if ( psaux && psaux->afm_parser_funcs )
00256     {
00257       error = psaux->afm_parser_funcs->init( &parser,
00258                                              stream->memory,
00259                                              stream->cursor,
00260                                              stream->limit );
00261 
00262       if ( !error )
00263       {
00264         parser.FontInfo  = fi;
00265         parser.get_index = t1_get_index;
00266         parser.user_data = t1_font;
00267 
00268         error = psaux->afm_parser_funcs->parse( &parser );
00269         psaux->afm_parser_funcs->done( &parser );
00270       }
00271     }
00272 
00273     if ( error == T1_Err_Unknown_File_Format )
00274     {
00275       FT_Byte*  start = stream->cursor;
00276 
00277 
00278       /* MS Windows allows versions up to 0x3FF without complaining */
00279       if ( stream->size > 6                              &&
00280            start[1] < 4                                  &&
00281            FT_PEEK_ULONG_LE( start + 2 ) == stream->size )
00282         error = T1_Read_PFM( t1_face, stream, fi );
00283     }
00284 
00285     if ( !error )
00286     {
00287       t1_font->font_bbox = fi->FontBBox;
00288 
00289       t1_face->bbox.xMin =   fi->FontBBox.xMin            >> 16;
00290       t1_face->bbox.yMin =   fi->FontBBox.yMin            >> 16;
00291       /* no `U' suffix here to 0xFFFF! */
00292       t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16;
00293       t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16;
00294 
00295       /* no `U' suffix here to 0x8000! */
00296       t1_face->ascender  = (FT_Short)( ( fi->Ascender  + 0x8000 ) >> 16 );
00297       t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 );
00298 
00299       if ( fi->NumKernPair )
00300       {
00301         t1_face->face_flags |= FT_FACE_FLAG_KERNING;
00302         ( (T1_Face)t1_face )->afm_data = fi;
00303         fi = NULL;
00304       }
00305     }
00306 
00307     FT_FRAME_EXIT();
00308 
00309   Exit:
00310     if ( fi != NULL )
00311       T1_Done_Metrics( memory, fi );
00312 
00313     return error;
00314   }
00315 
00316 
00317   /* find the kerning for a given glyph pair */
00318   FT_LOCAL_DEF( void )
00319   T1_Get_Kerning( AFM_FontInfo  fi,
00320                   FT_UInt       glyph1,
00321                   FT_UInt       glyph2,
00322                   FT_Vector*    kerning )
00323   {
00324     AFM_KernPair  min, mid, max;
00325     FT_ULong      idx = KERN_INDEX( glyph1, glyph2 );
00326 
00327 
00328     /* simple binary search */
00329     min = fi->KernPairs;
00330     max = min + fi->NumKernPair - 1;
00331 
00332     while ( min <= max )
00333     {
00334       FT_ULong  midi;
00335 
00336 
00337       mid  = min + ( max - min ) / 2;
00338       midi = KERN_INDEX( mid->index1, mid->index2 );
00339 
00340       if ( midi == idx )
00341       {
00342         kerning->x = mid->x;
00343         kerning->y = mid->y;
00344 
00345         return;
00346       }
00347 
00348       if ( midi < idx )
00349         min = mid + 1;
00350       else
00351         max = mid - 1;
00352     }
00353 
00354     kerning->x = 0;
00355     kerning->y = 0;
00356   }
00357 
00358 
00359   FT_LOCAL_DEF( FT_Error )
00360   T1_Get_Track_Kerning( FT_Face    face,
00361                         FT_Fixed   ptsize,
00362                         FT_Int     degree,
00363                         FT_Fixed*  kerning )
00364   {
00365     AFM_FontInfo  fi = (AFM_FontInfo)( (T1_Face)face )->afm_data;
00366     FT_Int        i;
00367 
00368 
00369     if ( !fi )
00370       return T1_Err_Invalid_Argument;
00371 
00372     for ( i = 0; i < fi->NumTrackKern; i++ )
00373     {
00374       AFM_TrackKern  tk = fi->TrackKerns + i;
00375 
00376 
00377       if ( tk->degree != degree )
00378         continue;
00379 
00380       if ( ptsize < tk->min_ptsize )
00381         *kerning = tk->min_kern;
00382       else if ( ptsize > tk->max_ptsize )
00383         *kerning = tk->max_kern;
00384       else
00385       {
00386         *kerning = FT_MulDiv( ptsize - tk->min_ptsize,
00387                               tk->max_kern - tk->min_kern,
00388                               tk->max_ptsize - tk->min_ptsize ) +
00389                    tk->min_kern;
00390       }
00391     }
00392 
00393     return T1_Err_Ok;
00394   }
00395 
00396 
00397 /* END */

Generated on Fri May 25 2012 04:32:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.