tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pcfdrivr.c (21788B)


      1 /*  pcfdrivr.c
      2 
      3    FreeType font driver for pcf files
      4 
      5    Copyright (C) 2000-2004, 2006-2011, 2013, 2014 by
      6    Francesco Zappa Nardelli
      7 
      8 Permission is hereby granted, free of charge, to any person obtaining a copy
      9 of this software and associated documentation files (the "Software"), to deal
     10 in the Software without restriction, including without limitation the rights
     11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     12 copies of the Software, and to permit persons to whom the Software is
     13 furnished to do so, subject to the following conditions:
     14 
     15 The above copyright notice and this permission notice shall be included in
     16 all copies or substantial portions of the Software.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     24 THE SOFTWARE.
     25 */
     26 
     27 
     28 
     29 #include <freetype/internal/ftdebug.h>
     30 #include <freetype/internal/ftstream.h>
     31 #include <freetype/internal/ftobjs.h>
     32 #include <freetype/ftgzip.h>
     33 #include <freetype/ftlzw.h>
     34 #include <freetype/ftbzip2.h>
     35 #include <freetype/fterrors.h>
     36 #include <freetype/ftbdf.h>
     37 #include <freetype/ttnameid.h>
     38 
     39 #include "pcf.h"
     40 #include "pcfdrivr.h"
     41 #include "pcfread.h"
     42 
     43 #include "pcferror.h"
     44 #include "pcfutil.h"
     45 
     46 #undef  FT_COMPONENT
     47 #define FT_COMPONENT  pcfread
     48 
     49 #include <freetype/internal/services/svbdf.h>
     50 #include <freetype/internal/services/svfntfmt.h>
     51 #include <freetype/internal/services/svprop.h>
     52 #include <freetype/ftdriver.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  pcfdriver
     63 
     64 
     65  /*
     66   * This file uses X11 terminology for PCF data; an `encoding' in X11 speak
     67   * is the same as a `character code' in FreeType speak.
     68   */
     69  typedef struct  PCF_CMapRec_
     70  {
     71    FT_CMapRec  root;
     72    PCF_Enc     enc;
     73 
     74  } PCF_CMapRec, *PCF_CMap;
     75 
     76 
     77  FT_CALLBACK_DEF( FT_Error )
     78  pcf_cmap_init( FT_CMap     cmap,       /* PCF_CMap */
     79                 FT_Pointer  init_data )
     80  {
     81    PCF_CMap  pcfcmap = (PCF_CMap)cmap;
     82    PCF_Face  face    = (PCF_Face)FT_CMAP_FACE( cmap );
     83 
     84    FT_UNUSED( init_data );
     85 
     86 
     87    pcfcmap->enc = &face->enc;
     88 
     89    return FT_Err_Ok;
     90  }
     91 
     92 
     93  FT_CALLBACK_DEF( void )
     94  pcf_cmap_done( FT_CMap  cmap )         /* PCF_CMap */
     95  {
     96    PCF_CMap  pcfcmap = (PCF_CMap)cmap;
     97 
     98 
     99    pcfcmap->enc = NULL;
    100  }
    101 
    102 
    103  FT_CALLBACK_DEF( FT_UInt )
    104  pcf_cmap_char_index( FT_CMap    cmap,      /* PCF_CMap */
    105                       FT_UInt32  charcode )
    106  {
    107    PCF_Enc  enc = ( (PCF_CMap)cmap )->enc;
    108 
    109    FT_UInt32  i = ( charcode >> 8   ) - enc->firstRow;
    110    FT_UInt32  j = ( charcode & 0xFF ) - enc->firstCol;
    111    FT_UInt32  h = enc->lastRow - enc->firstRow + 1;
    112    FT_UInt32  w = enc->lastCol - enc->firstCol + 1;
    113 
    114 
    115    /* wrapped around "negative" values are also rejected */
    116    if ( i >= h || j >= w )
    117      return 0;
    118 
    119    return (FT_UInt)enc->offset[i * w + j];
    120  }
    121 
    122 
    123  FT_CALLBACK_DEF( FT_UInt )
    124  pcf_cmap_char_next( FT_CMap     cmap,       /* PCF_CMap */
    125                      FT_UInt32  *acharcode )
    126  {
    127    PCF_Enc    enc = ( (PCF_CMap)cmap )->enc;
    128    FT_UInt32  charcode = *acharcode + 1;
    129 
    130    FT_UInt32  i = ( charcode >> 8   ) - enc->firstRow;
    131    FT_UInt32  j = ( charcode & 0xFF ) - enc->firstCol;
    132    FT_UInt32  h = enc->lastRow - enc->firstRow + 1;
    133    FT_UInt32  w = enc->lastCol - enc->firstCol + 1;
    134 
    135    FT_UInt  result = 0;
    136 
    137 
    138    /* adjust wrapped around "negative" values */
    139    if ( (FT_Int32)i < 0 )
    140      i = 0;
    141    if ( (FT_Int32)j < 0 )
    142      j = 0;
    143 
    144    for ( ; i < h; i++, j = 0 )
    145      for ( ; j < w; j++ )
    146      {
    147        result = (FT_UInt)enc->offset[i * w + j];
    148        if ( result != 0xFFFFU )
    149          goto Exit;
    150      }
    151 
    152  Exit:
    153    *acharcode = ( ( i + enc->firstRow ) << 8 ) | ( j + enc->firstCol );
    154 
    155    return result;
    156  }
    157 
    158 
    159  static
    160  const FT_CMap_ClassRec  pcf_cmap_class =
    161  {
    162    sizeof ( PCF_CMapRec ),
    163    pcf_cmap_init,
    164    pcf_cmap_done,
    165    pcf_cmap_char_index,
    166    pcf_cmap_char_next,
    167 
    168    NULL, NULL, NULL, NULL, NULL
    169  };
    170 
    171 
    172  FT_CALLBACK_DEF( void )
    173  PCF_Face_Done( FT_Face  face )    /* PCF_Face */
    174  {
    175    PCF_Face   pcfface = (PCF_Face)face;
    176    FT_Memory  memory;
    177 
    178 
    179    if ( !face )
    180      return;
    181 
    182    memory = FT_FACE_MEMORY( face );
    183 
    184    FT_FREE( pcfface->metrics );
    185    FT_FREE( pcfface->enc.offset );
    186 
    187    /* free properties */
    188    if ( pcfface->properties )
    189    {
    190      FT_Int  i;
    191 
    192 
    193      for ( i = 0; i < pcfface->nprops; i++ )
    194      {
    195        PCF_Property  prop = &pcfface->properties[i];
    196 
    197 
    198        if ( prop )
    199        {
    200          FT_FREE( prop->name );
    201          if ( prop->isString )
    202            FT_FREE( prop->value.atom );
    203        }
    204      }
    205 
    206      FT_FREE( pcfface->properties );
    207    }
    208 
    209    FT_FREE( pcfface->toc.tables );
    210    FT_FREE( face->family_name );
    211    FT_FREE( face->style_name );
    212    FT_FREE( face->available_sizes );
    213    FT_FREE( pcfface->charset_encoding );
    214    FT_FREE( pcfface->charset_registry );
    215 
    216    /* close compressed stream if any */
    217    if ( face->stream == &pcfface->comp_stream )
    218    {
    219      FT_Stream_Close( &pcfface->comp_stream );
    220      face->stream = pcfface->comp_source;
    221    }
    222  }
    223 
    224 
    225  FT_CALLBACK_DEF( FT_Error )
    226  PCF_Face_Init( FT_Stream      stream,
    227                 FT_Face        face,       /* PCF_Face */
    228                 FT_Int         face_index,
    229                 FT_Int         num_params,
    230                 FT_Parameter*  params )
    231  {
    232    PCF_Face  pcfface = (PCF_Face)face;
    233    FT_Error  error;
    234 
    235    FT_UNUSED( num_params );
    236    FT_UNUSED( params );
    237 
    238 
    239    FT_TRACE2(( "PCF driver\n" ));
    240 
    241    error = pcf_load_font( stream, pcfface, face_index );
    242    if ( error )
    243    {
    244      PCF_Face_Done( face );
    245 
    246 #if defined( FT_CONFIG_OPTION_USE_ZLIB )  || \
    247    defined( FT_CONFIG_OPTION_USE_LZW )   || \
    248    defined( FT_CONFIG_OPTION_USE_BZIP2 )
    249 
    250 #ifdef FT_CONFIG_OPTION_USE_ZLIB
    251      {
    252        FT_Error  error2;
    253 
    254 
    255        /* this didn't work, try gzip support! */
    256        FT_TRACE2(( "  ... try gzip stream\n" ));
    257        error2 = FT_Stream_OpenGzip( &pcfface->comp_stream, stream );
    258        if ( FT_ERR_EQ( error2, Unimplemented_Feature ) )
    259          goto Fail;
    260 
    261        error = error2;
    262      }
    263 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
    264 
    265 #ifdef FT_CONFIG_OPTION_USE_LZW
    266      if ( error )
    267      {
    268        FT_Error  error3;
    269 
    270 
    271        /* this didn't work, try LZW support! */
    272        FT_TRACE2(( "  ... try LZW stream\n" ));
    273        error3 = FT_Stream_OpenLZW( &pcfface->comp_stream, stream );
    274        if ( FT_ERR_EQ( error3, Unimplemented_Feature ) )
    275          goto Fail;
    276 
    277        error = error3;
    278      }
    279 #endif /* FT_CONFIG_OPTION_USE_LZW */
    280 
    281 #ifdef FT_CONFIG_OPTION_USE_BZIP2
    282      if ( error )
    283      {
    284        FT_Error  error4;
    285 
    286 
    287        /* this didn't work, try Bzip2 support! */
    288        FT_TRACE2(( "  ... try Bzip2 stream\n" ));
    289        error4 = FT_Stream_OpenBzip2( &pcfface->comp_stream, stream );
    290        if ( FT_ERR_EQ( error4, Unimplemented_Feature ) )
    291          goto Fail;
    292 
    293        error = error4;
    294      }
    295 #endif /* FT_CONFIG_OPTION_USE_BZIP2 */
    296 
    297      if ( error )
    298        goto Fail;
    299 
    300      pcfface->comp_source = stream;
    301      face->stream         = &pcfface->comp_stream;
    302 
    303      stream = face->stream;
    304 
    305      error = pcf_load_font( stream, pcfface, face_index );
    306      if ( error )
    307        goto Fail;
    308 
    309 #else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
    310           FT_CONFIG_OPTION_USE_LZW ||
    311           FT_CONFIG_OPTION_USE_BZIP2) */
    312 
    313      goto Fail;
    314 
    315 #endif
    316    }
    317 
    318    /* PCF cannot have multiple faces in a single font file.
    319     * XXX: A non-zero face_index is already an invalid argument, but
    320     *      Type1, Type42 drivers have a convention to return
    321     *      an invalid argument error when the font could be
    322     *      opened by the specified driver.
    323     */
    324    if ( face_index < 0 )
    325      goto Exit;
    326    else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
    327    {
    328      FT_ERROR(( "PCF_Face_Init: invalid face index\n" ));
    329      PCF_Face_Done( face );
    330      return FT_THROW( Invalid_Argument );
    331    }
    332 
    333    /* set up charmap */
    334    {
    335      FT_String  *charset_registry = pcfface->charset_registry;
    336      FT_String  *charset_encoding = pcfface->charset_encoding;
    337      FT_Bool     unicode_charmap  = 0;
    338 
    339 
    340      if ( charset_registry && charset_encoding )
    341      {
    342        char*  s = charset_registry;
    343 
    344 
    345        /* Uh, oh, compare first letters manually to avoid dependency
    346           on locales. */
    347        if ( ( s[0] == 'i' || s[0] == 'I' ) &&
    348             ( s[1] == 's' || s[1] == 'S' ) &&
    349             ( s[2] == 'o' || s[2] == 'O' ) )
    350        {
    351          s += 3;
    352          if ( !ft_strcmp( s, "10646" )                         ||
    353               ( !ft_strcmp( s, "8859" )                      &&
    354                 !ft_strcmp( pcfface->charset_encoding, "1" ) ) )
    355            unicode_charmap = 1;
    356          /* another name for ASCII */
    357          else if ( !ft_strcmp( s, "646.1991" )                    &&
    358                    !ft_strcmp( pcfface->charset_encoding, "IRV" ) )
    359            unicode_charmap = 1;
    360        }
    361      }
    362 
    363      {
    364        FT_CharMapRec  charmap;
    365 
    366 
    367        charmap.face        = face;
    368        charmap.encoding    = FT_ENCODING_NONE;
    369        /* initial platform/encoding should indicate unset status? */
    370        charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
    371        charmap.encoding_id = TT_APPLE_ID_DEFAULT;
    372 
    373        if ( unicode_charmap )
    374        {
    375          charmap.encoding    = FT_ENCODING_UNICODE;
    376          charmap.platform_id = TT_PLATFORM_MICROSOFT;
    377          charmap.encoding_id = TT_MS_ID_UNICODE_CS;
    378        }
    379 
    380        error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
    381      }
    382    }
    383 
    384  Exit:
    385    return error;
    386 
    387  Fail:
    388    FT_TRACE2(( "  not a PCF file\n" ));
    389    PCF_Face_Done( face );
    390    error = FT_THROW( Unknown_File_Format );  /* error */
    391    goto Exit;
    392  }
    393 
    394 
    395  FT_CALLBACK_DEF( FT_Error )
    396  PCF_Size_Select( FT_Size   size,
    397                   FT_ULong  strike_index )
    398  {
    399    PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
    400 
    401 
    402    FT_Select_Metrics( size->face, strike_index );
    403 
    404    size->metrics.ascender    =  accel->fontAscent * 64;
    405    size->metrics.descender   = -accel->fontDescent * 64;
    406    size->metrics.max_advance =  accel->maxbounds.characterWidth * 64;
    407 
    408    return FT_Err_Ok;
    409  }
    410 
    411 
    412  FT_CALLBACK_DEF( FT_Error )
    413  PCF_Size_Request( FT_Size          size,
    414                    FT_Size_Request  req )
    415  {
    416    PCF_Face         face  = (PCF_Face)size->face;
    417    FT_Bitmap_Size*  bsize = size->face->available_sizes;
    418    FT_Error         error = FT_ERR( Invalid_Pixel_Size );
    419    FT_Long          height;
    420 
    421 
    422    height = FT_REQUEST_HEIGHT( req );
    423    height = ( height + 32 ) >> 6;
    424 
    425    switch ( req->type )
    426    {
    427    case FT_SIZE_REQUEST_TYPE_NOMINAL:
    428      if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
    429        error = FT_Err_Ok;
    430      break;
    431 
    432    case FT_SIZE_REQUEST_TYPE_REAL_DIM:
    433      if ( height == ( face->accel.fontAscent +
    434                       face->accel.fontDescent ) )
    435        error = FT_Err_Ok;
    436      break;
    437 
    438    default:
    439      error = FT_THROW( Unimplemented_Feature );
    440      break;
    441    }
    442 
    443    if ( error )
    444      return error;
    445    else
    446      return PCF_Size_Select( size, 0 );
    447  }
    448 
    449 
    450  FT_CALLBACK_DEF( FT_Error )
    451  PCF_Glyph_Load( FT_GlyphSlot  slot,
    452                  FT_Size       size,
    453                  FT_UInt       glyph_index,
    454                  FT_Int32      load_flags )
    455  {
    456    PCF_Face    face   = (PCF_Face)size->face;
    457    FT_Stream   stream;
    458    FT_Error    error  = FT_Err_Ok;
    459    FT_Bitmap*  bitmap = &slot->bitmap;
    460    PCF_Metric  metric;
    461    FT_ULong    bytes;
    462 
    463 
    464    FT_TRACE1(( "PCF_Glyph_Load: glyph index %u\n", glyph_index ));
    465 
    466    if ( !face )
    467    {
    468      error = FT_THROW( Invalid_Face_Handle );
    469      goto Exit;
    470    }
    471 
    472    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
    473    {
    474      error = FT_THROW( Invalid_Argument );
    475      goto Exit;
    476    }
    477 
    478    stream = face->root.stream;
    479 
    480    metric = face->metrics + glyph_index;
    481 
    482    bitmap->rows       = (unsigned int)( metric->ascent +
    483                                         metric->descent );
    484    bitmap->width      = (unsigned int)( metric->rightSideBearing -
    485                                         metric->leftSideBearing );
    486    bitmap->num_grays  = 1;
    487    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
    488 
    489    switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
    490    {
    491    case 1:
    492      bitmap->pitch = (int)( ( bitmap->width + 7 ) >> 3 );
    493      break;
    494 
    495    case 2:
    496      bitmap->pitch = (int)( ( ( bitmap->width + 15 ) >> 4 ) << 1 );
    497      break;
    498 
    499    case 4:
    500      bitmap->pitch = (int)( ( ( bitmap->width + 31 ) >> 5 ) << 2 );
    501      break;
    502 
    503    case 8:
    504      bitmap->pitch = (int)( ( ( bitmap->width + 63 ) >> 6 ) << 3 );
    505      break;
    506 
    507    default:
    508      return FT_THROW( Invalid_File_Format );
    509    }
    510 
    511    slot->format      = FT_GLYPH_FORMAT_BITMAP;
    512    slot->bitmap_left = metric->leftSideBearing;
    513    slot->bitmap_top  = metric->ascent;
    514 
    515    slot->metrics.horiAdvance  = (FT_Pos)( metric->characterWidth * 64 );
    516    slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 );
    517    slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 );
    518    slot->metrics.width        = (FT_Pos)( ( metric->rightSideBearing -
    519                                             metric->leftSideBearing ) * 64 );
    520    slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
    521 
    522    ft_synthesize_vertical_metrics( &slot->metrics,
    523                                    ( face->accel.fontAscent +
    524                                      face->accel.fontDescent ) * 64 );
    525 
    526    if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY )
    527      goto Exit;
    528 
    529    /* XXX: to do: are there cases that need repadding the bitmap? */
    530    bytes = (FT_ULong)bitmap->pitch * bitmap->rows;
    531 
    532    error = ft_glyphslot_alloc_bitmap( slot, (FT_ULong)bytes );
    533    if ( error )
    534      goto Exit;
    535 
    536    if ( FT_STREAM_SEEK( metric->bits )          ||
    537         FT_STREAM_READ( bitmap->buffer, bytes ) )
    538      goto Exit;
    539 
    540    if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
    541      BitOrderInvert( bitmap->buffer, bytes );
    542 
    543    if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
    544           PCF_BIT_ORDER( face->bitmapsFormat )  ) )
    545    {
    546      switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
    547      {
    548      case 1:
    549        break;
    550 
    551      case 2:
    552        TwoByteSwap( bitmap->buffer, bytes );
    553        break;
    554 
    555      case 4:
    556        FourByteSwap( bitmap->buffer, bytes );
    557        break;
    558      }
    559    }
    560 
    561  Exit:
    562    return error;
    563  }
    564 
    565 
    566  /*
    567   *
    568   * BDF SERVICE
    569   *
    570   */
    571 
    572  FT_CALLBACK_DEF( FT_Error )
    573  pcf_get_bdf_property( FT_Face           face,       /* PCF_Face */
    574                        const char*       prop_name,
    575                        BDF_PropertyRec  *aproperty )
    576  {
    577    PCF_Face      pcfface = (PCF_Face)face;
    578    PCF_Property  prop;
    579 
    580 
    581    prop = pcf_find_property( pcfface, prop_name );
    582    if ( prop )
    583    {
    584      if ( prop->isString )
    585      {
    586        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
    587        aproperty->u.atom = prop->value.atom;
    588      }
    589      else
    590      {
    591        if ( prop->value.l > 0x7FFFFFFFL          ||
    592             prop->value.l < ( -1 - 0x7FFFFFFFL ) )
    593        {
    594          FT_TRACE2(( "pcf_get_bdf_property:"
    595                      " too large integer 0x%lx is truncated\n",
    596                      prop->value.l ));
    597        }
    598 
    599        /*
    600         * The PCF driver loads all properties as signed integers.
    601         * This really doesn't seem to be a problem, because this is
    602         * sufficient for any meaningful values.
    603         */
    604        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
    605        aproperty->u.integer = (FT_Int32)prop->value.l;
    606      }
    607 
    608      return FT_Err_Ok;
    609    }
    610 
    611    return FT_THROW( Invalid_Argument );
    612  }
    613 
    614 
    615  FT_CALLBACK_DEF( FT_Error )
    616  pcf_get_charset_id( FT_Face       face,               /* PCF_Face */
    617                      const char*  *acharset_encoding,
    618                      const char*  *acharset_registry )
    619  {
    620    PCF_Face  pcfface = (PCF_Face)face;
    621 
    622 
    623    *acharset_encoding = pcfface->charset_encoding;
    624    *acharset_registry = pcfface->charset_registry;
    625 
    626    return FT_Err_Ok;
    627  }
    628 
    629 
    630  static const FT_Service_BDFRec  pcf_service_bdf =
    631  {
    632    (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,     /* get_charset_id */
    633    (FT_BDF_GetPropertyFunc) pcf_get_bdf_property    /* get_property   */
    634  };
    635 
    636 
    637  /*
    638   * PROPERTY SERVICE
    639   *
    640   */
    641  FT_CALLBACK_DEF( FT_Error )
    642  pcf_property_set( FT_Module    module,         /* PCF_Driver */
    643                    const char*  property_name,
    644                    const void*  value,
    645                    FT_Bool      value_is_string )
    646  {
    647 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
    648 
    649    FT_Error    error  = FT_Err_Ok;
    650    PCF_Driver  driver = (PCF_Driver)module;
    651 
    652 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    653    FT_UNUSED( value_is_string );
    654 #endif
    655 
    656 
    657    if ( !ft_strcmp( property_name, "no-long-family-names" ) )
    658    {
    659 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    660      if ( value_is_string )
    661      {
    662        const char*  s   = (const char*)value;
    663        long         lfn = ft_strtol( s, NULL, 10 );
    664 
    665 
    666        if ( lfn == 0 )
    667          driver->no_long_family_names = 0;
    668        else if ( lfn == 1 )
    669          driver->no_long_family_names = 1;
    670        else
    671          return FT_THROW( Invalid_Argument );
    672      }
    673      else
    674 #endif
    675      {
    676        FT_Bool*  no_long_family_names = (FT_Bool*)value;
    677 
    678 
    679        driver->no_long_family_names = *no_long_family_names;
    680      }
    681 
    682      return error;
    683    }
    684 
    685 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
    686 
    687    FT_UNUSED( module );
    688    FT_UNUSED( value );
    689    FT_UNUSED( value_is_string );
    690 #ifndef FT_DEBUG_LEVEL_TRACE
    691    FT_UNUSED( property_name );
    692 #endif
    693 
    694 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
    695 
    696    FT_TRACE2(( "pcf_property_set: missing property `%s'\n",
    697                property_name ));
    698    return FT_THROW( Missing_Property );
    699  }
    700 
    701 
    702  FT_CALLBACK_DEF( FT_Error )
    703  pcf_property_get( FT_Module    module,         /* PCF_Driver */
    704                    const char*  property_name,
    705                    void*        value )
    706  {
    707 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
    708 
    709    FT_Error    error  = FT_Err_Ok;
    710    PCF_Driver  driver = (PCF_Driver)module;
    711 
    712 
    713    if ( !ft_strcmp( property_name, "no-long-family-names" ) )
    714    {
    715      FT_Bool   no_long_family_names = driver->no_long_family_names;
    716      FT_Bool*  val                  = (FT_Bool*)value;
    717 
    718 
    719      *val = no_long_family_names;
    720 
    721      return error;
    722    }
    723 
    724 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
    725 
    726    FT_UNUSED( module );
    727    FT_UNUSED( value );
    728 #ifndef FT_DEBUG_LEVEL_TRACE
    729    FT_UNUSED( property_name );
    730 #endif
    731 
    732 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
    733 
    734    FT_TRACE2(( "pcf_property_get: missing property `%s'\n",
    735                property_name ));
    736    return FT_THROW( Missing_Property );
    737  }
    738 
    739 
    740  FT_DEFINE_SERVICE_PROPERTIESREC(
    741    pcf_service_properties,
    742 
    743    (FT_Properties_SetFunc)pcf_property_set,      /* set_property */
    744    (FT_Properties_GetFunc)pcf_property_get )     /* get_property */
    745 
    746 
    747  /*
    748   *
    749   * SERVICE LIST
    750   *
    751   */
    752 
    753  static const FT_ServiceDescRec  pcf_services[] =
    754  {
    755    { FT_SERVICE_ID_BDF,         &pcf_service_bdf },
    756    { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF },
    757    { FT_SERVICE_ID_PROPERTIES,  &pcf_service_properties },
    758    { NULL, NULL }
    759  };
    760 
    761 
    762  FT_CALLBACK_DEF( FT_Module_Interface )
    763  pcf_driver_requester( FT_Module    module,
    764                        const char*  name )
    765  {
    766    FT_UNUSED( module );
    767 
    768    return ft_service_list_lookup( pcf_services, name );
    769  }
    770 
    771 
    772  FT_CALLBACK_DEF( FT_Error )
    773  pcf_driver_init( FT_Module  module )      /* PCF_Driver */
    774  {
    775 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
    776    PCF_Driver  driver = (PCF_Driver)module;
    777 
    778 
    779    driver->no_long_family_names = 0;
    780 #else
    781    FT_UNUSED( module );
    782 #endif
    783 
    784    return FT_Err_Ok;
    785  }
    786 
    787 
    788  FT_CALLBACK_DEF( void )
    789  pcf_driver_done( FT_Module  module )      /* PCF_Driver */
    790  {
    791    FT_UNUSED( module );
    792  }
    793 
    794 
    795  FT_CALLBACK_TABLE_DEF
    796  const FT_Driver_ClassRec  pcf_driver_class =
    797  {
    798    {
    799      FT_MODULE_FONT_DRIVER        |
    800      FT_MODULE_DRIVER_NO_OUTLINES,
    801 
    802      sizeof ( PCF_DriverRec ),
    803      "pcf",
    804      0x10000L,
    805      0x20000L,
    806 
    807      NULL,   /* module-specific interface */
    808 
    809      pcf_driver_init,          /* FT_Module_Constructor  module_init   */
    810      pcf_driver_done,          /* FT_Module_Destructor   module_done   */
    811      pcf_driver_requester      /* FT_Module_Requester    get_interface */
    812    },
    813 
    814    sizeof ( PCF_FaceRec ),
    815    sizeof ( FT_SizeRec ),
    816    sizeof ( FT_GlyphSlotRec ),
    817 
    818    PCF_Face_Init,              /* FT_Face_InitFunc  init_face */
    819    PCF_Face_Done,              /* FT_Face_DoneFunc  done_face */
    820    NULL,                       /* FT_Size_InitFunc  init_size */
    821    NULL,                       /* FT_Size_DoneFunc  done_size */
    822    NULL,                       /* FT_Slot_InitFunc  init_slot */
    823    NULL,                       /* FT_Slot_DoneFunc  done_slot */
    824 
    825    PCF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
    826 
    827    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
    828    NULL,                       /* FT_Face_AttachFunc       attach_file  */
    829    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
    830 
    831    PCF_Size_Request,           /* FT_Size_RequestFunc  request_size */
    832    PCF_Size_Select             /* FT_Size_SelectFunc   select_size  */
    833  };
    834 
    835 
    836 /* END */