misc/libfreetype/src/pcf/pcfdrivr.c
branchwebgl
changeset 9521 8054d9d775fd
parent 9282 92af50454cf2
parent 9519 b8b5c82eb61b
child 9950 2759212a27de
equal deleted inserted replaced
9282:92af50454cf2 9521:8054d9d775fd
     1 /*  pcfdrivr.c
       
     2 
       
     3     FreeType font driver for pcf files
       
     4 
       
     5     Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009,
       
     6                   2010 by
       
     7     Francesco Zappa Nardelli
       
     8 
       
     9 Permission is hereby granted, free of charge, to any person obtaining a copy
       
    10 of this software and associated documentation files (the "Software"), to deal
       
    11 in the Software without restriction, including without limitation the rights
       
    12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    13 copies of the Software, and to permit persons to whom the Software is
       
    14 furnished to do so, subject to the following conditions:
       
    15 
       
    16 The above copyright notice and this permission notice shall be included in
       
    17 all copies or substantial portions of the Software.
       
    18 
       
    19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
       
    22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    25 THE SOFTWARE.
       
    26 */
       
    27 
       
    28 
       
    29 #include <ft2build.h>
       
    30 
       
    31 #include FT_INTERNAL_DEBUG_H
       
    32 #include FT_INTERNAL_STREAM_H
       
    33 #include FT_INTERNAL_OBJECTS_H
       
    34 #include FT_GZIP_H
       
    35 #include FT_LZW_H
       
    36 #include FT_BZIP2_H
       
    37 #include FT_ERRORS_H
       
    38 #include FT_BDF_H
       
    39 #include FT_TRUETYPE_IDS_H 
       
    40 
       
    41 #include "pcf.h"
       
    42 #include "pcfdrivr.h"
       
    43 #include "pcfread.h"
       
    44 
       
    45 #include "pcferror.h"
       
    46 #include "pcfutil.h"
       
    47 
       
    48 #undef  FT_COMPONENT
       
    49 #define FT_COMPONENT  trace_pcfread
       
    50 
       
    51 #include FT_SERVICE_BDF_H
       
    52 #include FT_SERVICE_XFREE86_NAME_H
       
    53 
       
    54 
       
    55   /*************************************************************************/
       
    56   /*                                                                       */
       
    57   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    58   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    59   /* messages during execution.                                            */
       
    60   /*                                                                       */
       
    61 #undef  FT_COMPONENT
       
    62 #define FT_COMPONENT  trace_pcfdriver
       
    63 
       
    64 
       
    65   typedef struct  PCF_CMapRec_
       
    66   {
       
    67     FT_CMapRec    root;
       
    68     FT_UInt       num_encodings;
       
    69     PCF_Encoding  encodings;
       
    70 
       
    71   } PCF_CMapRec, *PCF_CMap;
       
    72 
       
    73 
       
    74   FT_CALLBACK_DEF( FT_Error )
       
    75   pcf_cmap_init( FT_CMap     pcfcmap,   /* PCF_CMap */
       
    76                  FT_Pointer  init_data )
       
    77   {
       
    78     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
       
    79     PCF_Face  face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
       
    80 
       
    81     FT_UNUSED( init_data );
       
    82 
       
    83 
       
    84     cmap->num_encodings = (FT_UInt)face->nencodings;
       
    85     cmap->encodings     = face->encodings;
       
    86 
       
    87     return PCF_Err_Ok;
       
    88   }
       
    89 
       
    90 
       
    91   FT_CALLBACK_DEF( void )
       
    92   pcf_cmap_done( FT_CMap  pcfcmap )         /* PCF_CMap */
       
    93   {
       
    94     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
       
    95 
       
    96 
       
    97     cmap->encodings     = NULL;
       
    98     cmap->num_encodings = 0;
       
    99   }
       
   100 
       
   101 
       
   102   FT_CALLBACK_DEF( FT_UInt )
       
   103   pcf_cmap_char_index( FT_CMap    pcfcmap,  /* PCF_CMap */
       
   104                        FT_UInt32  charcode )
       
   105   {
       
   106     PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
       
   107     PCF_Encoding  encodings = cmap->encodings;
       
   108     FT_UInt       min, max, mid;
       
   109     FT_UInt       result    = 0;
       
   110 
       
   111 
       
   112     min = 0;
       
   113     max = cmap->num_encodings;
       
   114 
       
   115     while ( min < max )
       
   116     {
       
   117       FT_ULong  code;
       
   118 
       
   119 
       
   120       mid  = ( min + max ) >> 1;
       
   121       code = encodings[mid].enc;
       
   122 
       
   123       if ( charcode == code )
       
   124       {
       
   125         result = encodings[mid].glyph + 1;
       
   126         break;
       
   127       }
       
   128 
       
   129       if ( charcode < code )
       
   130         max = mid;
       
   131       else
       
   132         min = mid + 1;
       
   133     }
       
   134 
       
   135     return result;
       
   136   }
       
   137 
       
   138 
       
   139   FT_CALLBACK_DEF( FT_UInt )
       
   140   pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
       
   141                       FT_UInt32  *acharcode )
       
   142   {
       
   143     PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
       
   144     PCF_Encoding  encodings = cmap->encodings;
       
   145     FT_UInt       min, max, mid;
       
   146     FT_ULong      charcode  = *acharcode + 1;
       
   147     FT_UInt       result    = 0;
       
   148 
       
   149 
       
   150     min = 0;
       
   151     max = cmap->num_encodings;
       
   152 
       
   153     while ( min < max )
       
   154     {
       
   155       FT_ULong  code;
       
   156 
       
   157 
       
   158       mid  = ( min + max ) >> 1;
       
   159       code = encodings[mid].enc;
       
   160 
       
   161       if ( charcode == code )
       
   162       {
       
   163         result = encodings[mid].glyph + 1;
       
   164         goto Exit;
       
   165       }
       
   166 
       
   167       if ( charcode < code )
       
   168         max = mid;
       
   169       else
       
   170         min = mid + 1;
       
   171     }
       
   172 
       
   173     charcode = 0;
       
   174     if ( min < cmap->num_encodings )
       
   175     {
       
   176       charcode = encodings[min].enc;
       
   177       result   = encodings[min].glyph + 1;
       
   178     }
       
   179 
       
   180   Exit:
       
   181     if ( charcode > 0xFFFFFFFFUL )
       
   182     {
       
   183       FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
       
   184       *acharcode = 0;
       
   185       /* XXX: result should be changed to indicate an overflow error */
       
   186     }
       
   187     else
       
   188       *acharcode = (FT_UInt32)charcode;
       
   189     return result;
       
   190   }
       
   191 
       
   192 
       
   193   FT_CALLBACK_TABLE_DEF
       
   194   const FT_CMap_ClassRec  pcf_cmap_class =
       
   195   {
       
   196     sizeof ( PCF_CMapRec ),
       
   197     pcf_cmap_init,
       
   198     pcf_cmap_done,
       
   199     pcf_cmap_char_index,
       
   200     pcf_cmap_char_next,
       
   201 
       
   202     NULL, NULL, NULL, NULL, NULL
       
   203   };
       
   204 
       
   205 
       
   206   FT_CALLBACK_DEF( void )
       
   207   PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
       
   208   {
       
   209     PCF_Face   face = (PCF_Face)pcfface;
       
   210     FT_Memory  memory;
       
   211 
       
   212 
       
   213     if ( !face )
       
   214       return;
       
   215 
       
   216     memory = FT_FACE_MEMORY( face );
       
   217 
       
   218     FT_FREE( face->encodings );
       
   219     FT_FREE( face->metrics );
       
   220 
       
   221     /* free properties */
       
   222     {
       
   223       PCF_Property  prop;
       
   224       FT_Int        i;
       
   225 
       
   226 
       
   227       if ( face->properties )
       
   228       {
       
   229         for ( i = 0; i < face->nprops; i++ )
       
   230         {
       
   231           prop = &face->properties[i];
       
   232 
       
   233           if ( prop )
       
   234           {
       
   235             FT_FREE( prop->name );
       
   236             if ( prop->isString )
       
   237               FT_FREE( prop->value.atom );
       
   238           }
       
   239         }
       
   240       }
       
   241       FT_FREE( face->properties );
       
   242     }
       
   243 
       
   244     FT_FREE( face->toc.tables );
       
   245     FT_FREE( pcfface->family_name );
       
   246     FT_FREE( pcfface->style_name );
       
   247     FT_FREE( pcfface->available_sizes );
       
   248     FT_FREE( face->charset_encoding );
       
   249     FT_FREE( face->charset_registry );
       
   250 
       
   251     FT_TRACE4(( "PCF_Face_Done: done face\n" ));
       
   252 
       
   253     /* close compressed stream if any */
       
   254     if ( pcfface->stream == &face->comp_stream )
       
   255     {
       
   256       FT_Stream_Close( &face->comp_stream );
       
   257       pcfface->stream = face->comp_source;
       
   258     }
       
   259   }
       
   260 
       
   261 
       
   262   FT_CALLBACK_DEF( FT_Error )
       
   263   PCF_Face_Init( FT_Stream      stream,
       
   264                  FT_Face        pcfface,        /* PCF_Face */
       
   265                  FT_Int         face_index,
       
   266                  FT_Int         num_params,
       
   267                  FT_Parameter*  params )
       
   268   {
       
   269     PCF_Face  face  = (PCF_Face)pcfface;
       
   270     FT_Error  error = PCF_Err_Ok;
       
   271 
       
   272     FT_UNUSED( num_params );
       
   273     FT_UNUSED( params );
       
   274     FT_UNUSED( face_index );
       
   275 
       
   276 
       
   277     error = pcf_load_font( stream, face );
       
   278     if ( error )
       
   279     {
       
   280       PCF_Face_Done( pcfface );
       
   281 
       
   282 #if defined( FT_CONFIG_OPTION_USE_ZLIB )  || \
       
   283     defined( FT_CONFIG_OPTION_USE_LZW )   || \
       
   284     defined( FT_CONFIG_OPTION_USE_BZIP2 )
       
   285 
       
   286 #ifdef FT_CONFIG_OPTION_USE_ZLIB
       
   287       {
       
   288         FT_Error  error2;
       
   289 
       
   290 
       
   291         /* this didn't work, try gzip support! */
       
   292         error2 = FT_Stream_OpenGzip( &face->comp_stream, stream );
       
   293         if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
       
   294           goto Fail;
       
   295 
       
   296         error = error2;
       
   297       }
       
   298 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
       
   299 
       
   300 #ifdef FT_CONFIG_OPTION_USE_LZW
       
   301       if ( error )
       
   302       {
       
   303         FT_Error  error3;
       
   304 
       
   305 
       
   306         /* this didn't work, try LZW support! */
       
   307         error3 = FT_Stream_OpenLZW( &face->comp_stream, stream );
       
   308         if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
       
   309           goto Fail;
       
   310 
       
   311         error = error3;
       
   312       }
       
   313 #endif /* FT_CONFIG_OPTION_USE_LZW */
       
   314 
       
   315 #ifdef FT_CONFIG_OPTION_USE_BZIP2
       
   316       if ( error )
       
   317       {
       
   318         FT_Error  error4;
       
   319 
       
   320 
       
   321         /* this didn't work, try Bzip2 support! */
       
   322         error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream );
       
   323         if ( FT_ERROR_BASE( error4 ) == FT_Err_Unimplemented_Feature )
       
   324           goto Fail;
       
   325 
       
   326         error = error4;
       
   327       }
       
   328 #endif /* FT_CONFIG_OPTION_USE_BZIP2 */
       
   329 
       
   330       if ( error )
       
   331         goto Fail;
       
   332 
       
   333       face->comp_source = stream;
       
   334       pcfface->stream   = &face->comp_stream;
       
   335 
       
   336       stream = pcfface->stream;
       
   337 
       
   338       error = pcf_load_font( stream, face );
       
   339       if ( error )
       
   340         goto Fail;
       
   341 
       
   342 #else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
       
   343            FT_CONFIG_OPTION_USE_LZW ||
       
   344            FT_CONFIG_OPTION_USE_BZIP2) */
       
   345 
       
   346       goto Fail;
       
   347 
       
   348 #endif
       
   349     }
       
   350 
       
   351     /* set up charmap */
       
   352     {
       
   353       FT_String  *charset_registry = face->charset_registry;
       
   354       FT_String  *charset_encoding = face->charset_encoding;
       
   355       FT_Bool     unicode_charmap  = 0;
       
   356 
       
   357 
       
   358       if ( charset_registry && charset_encoding )
       
   359       {
       
   360         char*  s = charset_registry;
       
   361 
       
   362 
       
   363         /* Uh, oh, compare first letters manually to avoid dependency
       
   364            on locales. */
       
   365         if ( ( s[0] == 'i' || s[0] == 'I' ) &&
       
   366              ( s[1] == 's' || s[1] == 'S' ) &&
       
   367              ( s[2] == 'o' || s[2] == 'O' ) )
       
   368         {
       
   369           s += 3;
       
   370           if ( !ft_strcmp( s, "10646" )                      ||
       
   371                ( !ft_strcmp( s, "8859" ) &&
       
   372                  !ft_strcmp( face->charset_encoding, "1" ) ) )
       
   373           unicode_charmap = 1;
       
   374         }
       
   375       }
       
   376 
       
   377       {
       
   378         FT_CharMapRec  charmap;
       
   379 
       
   380 
       
   381         charmap.face        = FT_FACE( face );
       
   382         charmap.encoding    = FT_ENCODING_NONE;
       
   383         /* initial platform/encoding should indicate unset status? */
       
   384         charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
       
   385         charmap.encoding_id = TT_APPLE_ID_DEFAULT;
       
   386 
       
   387         if ( unicode_charmap )
       
   388         {
       
   389           charmap.encoding    = FT_ENCODING_UNICODE;
       
   390           charmap.platform_id = TT_PLATFORM_MICROSOFT;
       
   391           charmap.encoding_id = TT_MS_ID_UNICODE_CS;
       
   392         }
       
   393 
       
   394         error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
       
   395 
       
   396 #if 0
       
   397         /* Select default charmap */
       
   398         if ( pcfface->num_charmaps )
       
   399           pcfface->charmap = pcfface->charmaps[0];
       
   400 #endif
       
   401       }
       
   402     }
       
   403 
       
   404   Exit:
       
   405     return error;
       
   406 
       
   407   Fail:
       
   408     FT_TRACE2(( "[not a valid PCF file]\n" ));
       
   409     PCF_Face_Done( pcfface );
       
   410     error = PCF_Err_Unknown_File_Format;  /* error */
       
   411     goto Exit;
       
   412   }
       
   413 
       
   414 
       
   415   FT_CALLBACK_DEF( FT_Error )
       
   416   PCF_Size_Select( FT_Size   size,
       
   417                    FT_ULong  strike_index )
       
   418   {
       
   419     PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
       
   420 
       
   421 
       
   422     FT_Select_Metrics( size->face, strike_index );
       
   423 
       
   424     size->metrics.ascender    =  accel->fontAscent << 6;
       
   425     size->metrics.descender   = -accel->fontDescent << 6;
       
   426     size->metrics.max_advance =  accel->maxbounds.characterWidth << 6;
       
   427 
       
   428     return PCF_Err_Ok;
       
   429   }
       
   430 
       
   431 
       
   432   FT_CALLBACK_DEF( FT_Error )
       
   433   PCF_Size_Request( FT_Size          size,
       
   434                     FT_Size_Request  req )
       
   435   {
       
   436     PCF_Face         face  = (PCF_Face)size->face;
       
   437     FT_Bitmap_Size*  bsize = size->face->available_sizes;
       
   438     FT_Error         error = PCF_Err_Invalid_Pixel_Size;
       
   439     FT_Long          height;
       
   440 
       
   441 
       
   442     height = FT_REQUEST_HEIGHT( req );
       
   443     height = ( height + 32 ) >> 6;
       
   444 
       
   445     switch ( req->type )
       
   446     {
       
   447     case FT_SIZE_REQUEST_TYPE_NOMINAL:
       
   448       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
       
   449         error = PCF_Err_Ok;
       
   450       break;
       
   451 
       
   452     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
       
   453       if ( height == ( face->accel.fontAscent +
       
   454                        face->accel.fontDescent ) )
       
   455         error = PCF_Err_Ok;
       
   456       break;
       
   457 
       
   458     default:
       
   459       error = PCF_Err_Unimplemented_Feature;
       
   460       break;
       
   461     }
       
   462 
       
   463     if ( error )
       
   464       return error;
       
   465     else
       
   466       return PCF_Size_Select( size, 0 );
       
   467   }
       
   468 
       
   469 
       
   470   FT_CALLBACK_DEF( FT_Error )
       
   471   PCF_Glyph_Load( FT_GlyphSlot  slot,
       
   472                   FT_Size       size,
       
   473                   FT_UInt       glyph_index,
       
   474                   FT_Int32      load_flags )
       
   475   {
       
   476     PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
       
   477     FT_Stream   stream;
       
   478     FT_Error    error  = PCF_Err_Ok;
       
   479     FT_Bitmap*  bitmap = &slot->bitmap;
       
   480     PCF_Metric  metric;
       
   481     FT_Offset   bytes;
       
   482 
       
   483     FT_UNUSED( load_flags );
       
   484 
       
   485 
       
   486     FT_TRACE4(( "load_glyph %d ---", glyph_index ));
       
   487 
       
   488     if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs )
       
   489     {
       
   490       error = PCF_Err_Invalid_Argument;
       
   491       goto Exit;
       
   492     }
       
   493 
       
   494     stream = face->root.stream;
       
   495 
       
   496     if ( glyph_index > 0 )
       
   497       glyph_index--;
       
   498 
       
   499     metric = face->metrics + glyph_index;
       
   500 
       
   501     bitmap->rows       = metric->ascent + metric->descent;
       
   502     bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
       
   503     bitmap->num_grays  = 1;
       
   504     bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
       
   505 
       
   506     FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
       
   507                   PCF_BIT_ORDER( face->bitmapsFormat ),
       
   508                   PCF_BYTE_ORDER( face->bitmapsFormat ),
       
   509                   PCF_GLYPH_PAD( face->bitmapsFormat ) ));
       
   510 
       
   511     switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
       
   512     {
       
   513     case 1:
       
   514       bitmap->pitch = ( bitmap->width + 7 ) >> 3;
       
   515       break;
       
   516 
       
   517     case 2:
       
   518       bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
       
   519       break;
       
   520 
       
   521     case 4:
       
   522       bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
       
   523       break;
       
   524 
       
   525     case 8:
       
   526       bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
       
   527       break;
       
   528 
       
   529     default:
       
   530       return PCF_Err_Invalid_File_Format;
       
   531     }
       
   532 
       
   533     /* XXX: to do: are there cases that need repadding the bitmap? */
       
   534     bytes = bitmap->pitch * bitmap->rows;
       
   535 
       
   536     error = ft_glyphslot_alloc_bitmap( slot, bytes );
       
   537     if ( error )
       
   538       goto Exit;
       
   539 
       
   540     if ( FT_STREAM_SEEK( metric->bits )          ||
       
   541          FT_STREAM_READ( bitmap->buffer, bytes ) )
       
   542       goto Exit;
       
   543 
       
   544     if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
       
   545       BitOrderInvert( bitmap->buffer, bytes );
       
   546 
       
   547     if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
       
   548            PCF_BIT_ORDER( face->bitmapsFormat )  ) )
       
   549     {
       
   550       switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
       
   551       {
       
   552       case 1:
       
   553         break;
       
   554 
       
   555       case 2:
       
   556         TwoByteSwap( bitmap->buffer, bytes );
       
   557         break;
       
   558 
       
   559       case 4:
       
   560         FourByteSwap( bitmap->buffer, bytes );
       
   561         break;
       
   562       }
       
   563     }
       
   564 
       
   565     slot->format      = FT_GLYPH_FORMAT_BITMAP;
       
   566     slot->bitmap_left = metric->leftSideBearing;
       
   567     slot->bitmap_top  = metric->ascent;
       
   568 
       
   569     slot->metrics.horiAdvance  = metric->characterWidth << 6;
       
   570     slot->metrics.horiBearingX = metric->leftSideBearing << 6;
       
   571     slot->metrics.horiBearingY = metric->ascent << 6;
       
   572     slot->metrics.width        = ( metric->rightSideBearing -
       
   573                                    metric->leftSideBearing ) << 6;
       
   574     slot->metrics.height       = bitmap->rows << 6;
       
   575 
       
   576     ft_synthesize_vertical_metrics( &slot->metrics,
       
   577                                     ( face->accel.fontAscent +
       
   578                                       face->accel.fontDescent ) << 6 );
       
   579 
       
   580     FT_TRACE4(( " --- ok\n" ));
       
   581 
       
   582   Exit:
       
   583     return error;
       
   584   }
       
   585 
       
   586 
       
   587  /*
       
   588   *
       
   589   *  BDF SERVICE
       
   590   *
       
   591   */
       
   592 
       
   593   static FT_Error
       
   594   pcf_get_bdf_property( PCF_Face          face,
       
   595                         const char*       prop_name,
       
   596                         BDF_PropertyRec  *aproperty )
       
   597   {
       
   598     PCF_Property  prop;
       
   599 
       
   600 
       
   601     prop = pcf_find_property( face, prop_name );
       
   602     if ( prop != NULL )
       
   603     {
       
   604       if ( prop->isString )
       
   605       {
       
   606         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
       
   607         aproperty->u.atom = prop->value.atom;
       
   608       }
       
   609       else
       
   610       {
       
   611         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
       
   612         {
       
   613           FT_TRACE1(( "pcf_get_bdf_property: " ));
       
   614           FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
       
   615         }
       
   616         /* Apparently, the PCF driver loads all properties as signed integers!
       
   617          * This really doesn't seem to be a problem, because this is
       
   618          * sufficient for any meaningful values.
       
   619          */
       
   620         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
       
   621         aproperty->u.integer = (FT_Int32)prop->value.l;
       
   622       }
       
   623       return 0;
       
   624     }
       
   625 
       
   626     return PCF_Err_Invalid_Argument;
       
   627   }
       
   628 
       
   629 
       
   630   static FT_Error
       
   631   pcf_get_charset_id( PCF_Face      face,
       
   632                       const char*  *acharset_encoding,
       
   633                       const char*  *acharset_registry )
       
   634   {
       
   635     *acharset_encoding = face->charset_encoding;
       
   636     *acharset_registry = face->charset_registry;
       
   637 
       
   638     return 0;
       
   639   }
       
   640 
       
   641 
       
   642   static const FT_Service_BDFRec  pcf_service_bdf =
       
   643   {
       
   644     (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
       
   645     (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
       
   646   };
       
   647 
       
   648 
       
   649  /*
       
   650   *
       
   651   *  SERVICE LIST
       
   652   *
       
   653   */
       
   654 
       
   655   static const FT_ServiceDescRec  pcf_services[] =
       
   656   {
       
   657     { FT_SERVICE_ID_BDF,       &pcf_service_bdf },
       
   658     { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
       
   659     { NULL, NULL }
       
   660   };
       
   661 
       
   662 
       
   663   FT_CALLBACK_DEF( FT_Module_Interface )
       
   664   pcf_driver_requester( FT_Module    module,
       
   665                         const char*  name )
       
   666   {
       
   667     FT_UNUSED( module );
       
   668 
       
   669     return ft_service_list_lookup( pcf_services, name );
       
   670   }
       
   671 
       
   672 
       
   673   FT_CALLBACK_TABLE_DEF
       
   674   const FT_Driver_ClassRec  pcf_driver_class =
       
   675   {
       
   676     {
       
   677       FT_MODULE_FONT_DRIVER        |
       
   678       FT_MODULE_DRIVER_NO_OUTLINES,
       
   679       sizeof ( FT_DriverRec ),
       
   680 
       
   681       "pcf",
       
   682       0x10000L,
       
   683       0x20000L,
       
   684 
       
   685       0,
       
   686 
       
   687       0,
       
   688       0,
       
   689       pcf_driver_requester
       
   690     },
       
   691 
       
   692     sizeof ( PCF_FaceRec ),
       
   693     sizeof ( FT_SizeRec ),
       
   694     sizeof ( FT_GlyphSlotRec ),
       
   695 
       
   696     PCF_Face_Init,
       
   697     PCF_Face_Done,
       
   698     0,                      /* FT_Size_InitFunc */
       
   699     0,                      /* FT_Size_DoneFunc */
       
   700     0,                      /* FT_Slot_InitFunc */
       
   701     0,                      /* FT_Slot_DoneFunc */
       
   702 
       
   703 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
       
   704     ft_stub_set_char_sizes,
       
   705     ft_stub_set_pixel_sizes,
       
   706 #endif
       
   707     PCF_Glyph_Load,
       
   708 
       
   709     0,                      /* FT_Face_GetKerningFunc  */
       
   710     0,                      /* FT_Face_AttachFunc      */
       
   711     0,                      /* FT_Face_GetAdvancesFunc */
       
   712 
       
   713     PCF_Size_Request,
       
   714     PCF_Size_Select
       
   715   };
       
   716 
       
   717 
       
   718 /* END */