tor-browser

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

bdfdrivr.c (29464B)


      1 /*  bdfdrivr.c
      2 
      3    FreeType font driver for bdf files
      4 
      5    Copyright (C) 2001-2008, 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 #include <freetype/internal/ftdebug.h>
     29 #include <freetype/internal/ftstream.h>
     30 #include <freetype/internal/ftobjs.h>
     31 #include <freetype/ftbdf.h>
     32 #include <freetype/ttnameid.h>
     33 
     34 #include <freetype/internal/services/svbdf.h>
     35 #include <freetype/internal/services/svfntfmt.h>
     36 
     37 #include "bdf.h"
     38 #include "bdfdrivr.h"
     39 
     40 #include "bdferror.h"
     41 
     42 
     43  /**************************************************************************
     44   *
     45   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     46   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     47   * messages during execution.
     48   */
     49 #undef  FT_COMPONENT
     50 #define FT_COMPONENT  bdfdriver
     51 
     52 
     53  typedef struct  BDF_CMapRec_
     54  {
     55    FT_CMapRec        cmap;
     56    FT_ULong          num_encodings; /* ftobjs.h: FT_CMap->clazz->size */
     57    BDF_encoding_el*  encodings;
     58 
     59  } BDF_CMapRec, *BDF_CMap;
     60 
     61 
     62  FT_CALLBACK_DEF( FT_Error )
     63  bdf_cmap_init( FT_CMap     bdfcmap,
     64                 FT_Pointer  init_data )
     65  {
     66    BDF_CMap  cmap = (BDF_CMap)bdfcmap;
     67    BDF_Face  face = (BDF_Face)FT_CMAP_FACE( cmap );
     68    FT_UNUSED( init_data );
     69 
     70 
     71    cmap->num_encodings = face->bdffont->glyphs_used;
     72    cmap->encodings     = face->en_table;
     73 
     74    return FT_Err_Ok;
     75  }
     76 
     77 
     78  FT_CALLBACK_DEF( void )
     79  bdf_cmap_done( FT_CMap  bdfcmap )
     80  {
     81    BDF_CMap  cmap = (BDF_CMap)bdfcmap;
     82 
     83 
     84    cmap->encodings     = NULL;
     85    cmap->num_encodings = 0;
     86  }
     87 
     88 
     89  FT_CALLBACK_DEF( FT_UInt )
     90  bdf_cmap_char_index( FT_CMap    bdfcmap,
     91                       FT_UInt32  charcode )
     92  {
     93    BDF_CMap          cmap      = (BDF_CMap)bdfcmap;
     94    BDF_encoding_el*  encodings = cmap->encodings;
     95    FT_UShort         result    = 0; /* encodings->glyph */
     96 
     97    FT_ULong  min = 0;
     98    FT_ULong  max = cmap->num_encodings;
     99    FT_ULong  mid = ( min + max ) >> 1;
    100 
    101 
    102    while ( min < max )
    103    {
    104      FT_ULong  code = encodings[mid].enc;
    105 
    106 
    107      if ( charcode == code )
    108      {
    109        /* increase glyph index by 1 --              */
    110        /* we reserve slot 0 for the undefined glyph */
    111        result = encodings[mid].glyph + 1;
    112        break;
    113      }
    114 
    115      if ( charcode < code )
    116        max = mid;
    117      else
    118        min = mid + 1;
    119 
    120      /* reasonable prediction in a continuous block */
    121      mid += charcode - code;
    122      if ( mid >= max || mid < min )
    123        mid = ( min + max ) >> 1;
    124    }
    125 
    126    return result;
    127  }
    128 
    129 
    130  FT_CALLBACK_DEF( FT_UInt )
    131  bdf_cmap_char_next( FT_CMap     bdfcmap,
    132                      FT_UInt32  *acharcode )
    133  {
    134    BDF_CMap          cmap      = (BDF_CMap)bdfcmap;
    135    BDF_encoding_el*  encodings = cmap->encodings;
    136    FT_UShort         result   = 0;  /* encodings->glyph */
    137    FT_ULong          charcode = *acharcode + 1;
    138 
    139    FT_ULong  min = 0;
    140    FT_ULong  max = cmap->num_encodings;
    141    FT_ULong  mid = ( min + max ) >> 1;
    142 
    143 
    144    while ( min < max )
    145    {
    146      FT_ULong  code = encodings[mid].enc;
    147 
    148 
    149      if ( charcode == code )
    150      {
    151        /* increase glyph index by 1 --              */
    152        /* we reserve slot 0 for the undefined glyph */
    153        result = encodings[mid].glyph + 1;
    154        goto Exit;
    155      }
    156 
    157      if ( charcode < code )
    158        max = mid;
    159      else
    160        min = mid + 1;
    161 
    162      /* prediction in a continuous block */
    163      mid += charcode - code;
    164      if ( mid >= max || mid < min )
    165        mid = ( min + max ) >> 1;
    166    }
    167 
    168    charcode = 0;
    169    if ( min < cmap->num_encodings )
    170    {
    171      charcode = encodings[min].enc;
    172      result   = encodings[min].glyph + 1;
    173    }
    174 
    175  Exit:
    176    if ( charcode > 0xFFFFFFFFUL )
    177    {
    178      FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%lx > 32bit API",
    179                  charcode ));
    180      *acharcode = 0;
    181      /* XXX: result should be changed to indicate an overflow error */
    182    }
    183    else
    184      *acharcode = (FT_UInt32)charcode;
    185    return result;
    186  }
    187 
    188 
    189  static
    190  const FT_CMap_ClassRec  bdf_cmap_class =
    191  {
    192    sizeof ( BDF_CMapRec ),
    193    bdf_cmap_init,
    194    bdf_cmap_done,
    195    bdf_cmap_char_index,
    196    bdf_cmap_char_next,
    197 
    198    NULL, NULL, NULL, NULL, NULL
    199  };
    200 
    201 
    202  static FT_Error
    203  bdf_interpret_style( BDF_Face  bdf )
    204  {
    205    FT_Error         error  = FT_Err_Ok;
    206    FT_Face          face   = FT_FACE( bdf );
    207    FT_Memory        memory = face->memory;
    208    bdf_font_t*      font   = bdf->bdffont;
    209    bdf_property_t*  prop;
    210 
    211    const char*   strings[4] = { NULL, NULL, NULL, NULL };
    212    size_t        lengths[4], nn, len;
    213 
    214 
    215    face->style_flags = 0;
    216 
    217    prop = bdf_get_font_property( font, "SLANT" );
    218    if ( prop && prop->format == BDF_ATOM                             &&
    219         prop->value.atom                                             &&
    220         ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
    221           *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
    222    {
    223      face->style_flags |= FT_STYLE_FLAG_ITALIC;
    224      strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
    225                   ? "Oblique"
    226                   : "Italic";
    227    }
    228 
    229    prop = bdf_get_font_property( font, "WEIGHT_NAME" );
    230    if ( prop && prop->format == BDF_ATOM                             &&
    231         prop->value.atom                                             &&
    232         ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
    233    {
    234      face->style_flags |= FT_STYLE_FLAG_BOLD;
    235      strings[1] = "Bold";
    236    }
    237 
    238    prop = bdf_get_font_property( font, "SETWIDTH_NAME" );
    239    if ( prop && prop->format == BDF_ATOM                              &&
    240         prop->value.atom && *(prop->value.atom)                       &&
    241         !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
    242      strings[3] = (const char *)(prop->value.atom);
    243 
    244    prop = bdf_get_font_property( font, "ADD_STYLE_NAME" );
    245    if ( prop && prop->format == BDF_ATOM                              &&
    246         prop->value.atom && *(prop->value.atom)                       &&
    247         !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
    248      strings[0] = (const char *)(prop->value.atom);
    249 
    250    for ( len = 0, nn = 0; nn < 4; nn++ )
    251    {
    252      lengths[nn] = 0;
    253      if ( strings[nn] )
    254      {
    255        lengths[nn] = ft_strlen( strings[nn] );
    256        len        += lengths[nn] + 1;
    257      }
    258    }
    259 
    260    if ( len == 0 )
    261    {
    262      strings[0] = "Regular";
    263      lengths[0] = ft_strlen( strings[0] );
    264      len        = lengths[0] + 1;
    265    }
    266 
    267    {
    268      char*  s;
    269 
    270 
    271      if ( FT_QALLOC( face->style_name, len ) )
    272        return error;
    273 
    274      s = face->style_name;
    275 
    276      for ( nn = 0; nn < 4; nn++ )
    277      {
    278        const char*  src = strings[nn];
    279 
    280 
    281        len = lengths[nn];
    282 
    283        if ( !src )
    284          continue;
    285 
    286        /* separate elements with a space */
    287        if ( s != face->style_name )
    288          *s++ = ' ';
    289 
    290        ft_memcpy( s, src, len );
    291 
    292        /* need to convert spaces to dashes for */
    293        /* add_style_name and setwidth_name     */
    294        if ( nn == 0 || nn == 3 )
    295        {
    296          size_t  mm;
    297 
    298 
    299          for ( mm = 0; mm < len; mm++ )
    300            if ( s[mm] == ' ' )
    301              s[mm] = '-';
    302        }
    303 
    304        s += len;
    305      }
    306      *s = 0;
    307    }
    308 
    309    return error;
    310  }
    311 
    312 
    313  FT_CALLBACK_DEF( void )
    314  BDF_Face_Done( FT_Face  face )         /* BDF_Face */
    315  {
    316    BDF_Face   bdfface = (BDF_Face)face;
    317    FT_Memory  memory;
    318 
    319 
    320    if ( !face )
    321      return;
    322 
    323    memory = FT_FACE_MEMORY( face );
    324 
    325    bdf_free_font( bdfface->bdffont );
    326 
    327    FT_FREE( bdfface->en_table );
    328 
    329    FT_FREE( bdfface->charset_encoding );
    330    FT_FREE( bdfface->charset_registry );
    331    FT_FREE( face->family_name );
    332    FT_FREE( face->style_name );
    333 
    334    FT_FREE( face->available_sizes );
    335 
    336    FT_FREE( bdfface->bdffont );
    337  }
    338 
    339 
    340  FT_CALLBACK_DEF( FT_Error )
    341  BDF_Face_Init( FT_Stream      stream,
    342                 FT_Face        face,        /* BDF_Face */
    343                 FT_Int         face_index,
    344                 FT_Int         num_params,
    345                 FT_Parameter*  params )
    346  {
    347    FT_Error       error   = FT_Err_Ok;
    348    BDF_Face       bdfface = (BDF_Face)face;
    349    FT_Memory      memory  = FT_FACE_MEMORY( face );
    350 
    351    bdf_font_t*    font = NULL;
    352 
    353    FT_UNUSED( num_params );
    354    FT_UNUSED( params );
    355 
    356 
    357    FT_TRACE2(( "BDF driver\n" ));
    358 
    359    if ( FT_STREAM_SEEK( 0 ) )
    360      goto Exit;
    361 
    362    error = bdf_load_font( stream, memory,
    363                           BDF_CORRECT_METRICS | BDF_KEEP_UNENCODED, &font );
    364    if ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
    365    {
    366      FT_TRACE2(( "  not a BDF file\n" ));
    367      goto Fail;
    368    }
    369    else if ( error )
    370      goto Exit;
    371 
    372    /* we have a bdf font: let's construct the face object */
    373    bdfface->bdffont = font;
    374 
    375    /* BDF cannot have multiple faces in a single font file.
    376     * XXX: non-zero face_index is already invalid argument, but
    377     *      Type1, Type42 driver has a convention to return
    378     *      an invalid argument error when the font could be
    379     *      opened by the specified driver.
    380     */
    381    if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
    382    {
    383      FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
    384      BDF_Face_Done( face );
    385      return FT_THROW( Invalid_Argument );
    386    }
    387 
    388    {
    389      bdf_property_t*  prop = NULL;
    390 
    391 
    392      FT_TRACE4(( "  number of glyphs: allocated %lu (used %lu)\n",
    393                  font->glyphs_size,
    394                  font->glyphs_used ));
    395      FT_TRACE4(( "  number of unencoded glyphs: allocated %lu (used %lu)\n",
    396                  font->unencoded_size,
    397                  font->unencoded_used ));
    398 
    399      face->num_faces  = 1;
    400      face->face_index = 0;
    401 
    402      face->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
    403                          FT_FACE_FLAG_HORIZONTAL;
    404 
    405      prop = bdf_get_font_property( font, "SPACING" );
    406      if ( prop && prop->value.atom )
    407      {
    408        if      ( prop->value.atom[0] == 'p' || prop->value.atom[0] == 'P' )
    409          font->spacing = BDF_PROPORTIONAL;
    410        else if ( prop->value.atom[0] == 'm' || prop->value.atom[0] == 'M' )
    411          font->spacing = BDF_MONOWIDTH;
    412        else if ( prop->value.atom[0] == 'c' || prop->value.atom[0] == 'C' )
    413          font->spacing = BDF_CHARCELL;
    414      }
    415 
    416      if ( font->spacing == BDF_MONOWIDTH ||
    417           font->spacing == BDF_CHARCELL  )
    418        face->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
    419 
    420      /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL   */
    421      /* FZ XXX: I need a font to implement this */
    422 
    423      prop = bdf_get_font_property( font, "FAMILY_NAME" );
    424      if ( prop && prop->value.atom )
    425      {
    426        if ( FT_STRDUP( face->family_name, prop->value.atom ) )
    427          goto Exit;
    428      }
    429      else
    430        face->family_name = NULL;
    431 
    432      if ( FT_SET_ERROR( bdf_interpret_style( bdfface ) ) )
    433        goto Exit;
    434 
    435      /* the number of glyphs (with one slot for the undefined glyph */
    436      /* at position 0 and all unencoded glyphs)                     */
    437      face->num_glyphs = (FT_Long)( font->glyphs_size + 1 );
    438 
    439      face->num_fixed_sizes = 1;
    440      if ( FT_NEW( face->available_sizes ) )
    441        goto Exit;
    442 
    443      {
    444        FT_Bitmap_Size*  bsize        = face->available_sizes;
    445        FT_Short         resolution_x = 0;
    446        FT_Short         resolution_y = 0;
    447        long             value;
    448 
    449 
    450        prop = bdf_get_font_property( font, "FONT_ASCENT" );
    451        if ( prop )
    452          font->font_ascent = prop->value.l;
    453        else
    454          font->font_ascent = font->bbx.ascent;
    455        if ( font->font_ascent > 0x7FFF )
    456          font->font_ascent = 0x7FFF;
    457        else if ( font->font_ascent < 0 )
    458          font->font_ascent = 0;
    459 
    460        prop = bdf_get_font_property( font, "FONT_DESCENT" );
    461        if ( prop )
    462          font->font_descent = prop->value.l;
    463        else
    464          font->font_descent = font->bbx.descent;
    465        if ( font->font_descent > 0x7FFF )
    466          font->font_descent = 0x7FFF;
    467        else if ( font->font_descent < 0 )
    468          font->font_descent = 0;
    469 
    470        bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
    471 
    472        prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
    473        if ( prop )
    474        {
    475 #ifdef FT_DEBUG_LEVEL_TRACE
    476          if ( prop->value.l < 0 )
    477            FT_TRACE0(( "BDF_Face_Init: negative average width\n" ));
    478 #endif
    479          if ( prop->value.l >    0x7FFFL * 10 - 5   ||
    480               prop->value.l < -( 0x7FFFL * 10 - 5 ) )
    481          {
    482            bsize->width = 0x7FFF;
    483            FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n",
    484                        bsize->width ));
    485          }
    486          else
    487            bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
    488        }
    489        else
    490        {
    491          /* this is a heuristical value */
    492          bsize->width = ( bsize->height * 2 + 1 ) / 3;
    493        }
    494 
    495        prop = bdf_get_font_property( font, "POINT_SIZE" );
    496        if ( prop )
    497        {
    498 #ifdef FT_DEBUG_LEVEL_TRACE
    499          if ( prop->value.l < 0 )
    500            FT_TRACE0(( "BDF_Face_Init: negative point size\n" ));
    501 #endif
    502          /* convert from 722.7 decipoints to 72 points per inch */
    503          if ( prop->value.l >  0x504C2L || /* 0x7FFF * 72270/7200 */
    504               prop->value.l < -0x504C2L )
    505          {
    506            bsize->size = 0x7FFF;
    507            FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
    508                        bsize->size ));
    509          }
    510          else
    511            bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
    512                                     64 * 7200,
    513                                     72270L );
    514        }
    515        else if ( font->point_size )
    516        {
    517          if ( font->point_size > 0x7FFF )
    518          {
    519            bsize->size = 0x7FFF;
    520            FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
    521                        bsize->size ));
    522          }
    523          else
    524            bsize->size = (FT_Pos)font->point_size << 6;
    525        }
    526        else
    527        {
    528          /* this is a heuristical value */
    529          bsize->size = bsize->width * 64;
    530        }
    531 
    532        prop = bdf_get_font_property( font, "PIXEL_SIZE" );
    533        if ( prop )
    534        {
    535 #ifdef FT_DEBUG_LEVEL_TRACE
    536          if ( prop->value.l < 0 )
    537            FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" ));
    538 #endif
    539          if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF )
    540          {
    541            bsize->y_ppem = 0x7FFF << 6;
    542            FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %ld\n",
    543                        bsize->y_ppem ));
    544          }
    545          else
    546            bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
    547        }
    548 
    549        prop = bdf_get_font_property( font, "RESOLUTION_X" );
    550        if ( prop )
    551          value = prop->value.l;
    552        else
    553          value = (long)font->resolution_x;
    554        if ( value )
    555        {
    556 #ifdef FT_DEBUG_LEVEL_TRACE
    557          if ( value < 0 )
    558            FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" ));
    559 #endif
    560          if ( value > 0x7FFF || value < -0x7FFF )
    561          {
    562            resolution_x = 0x7FFF;
    563            FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n",
    564                        resolution_x ));
    565          }
    566          else
    567            resolution_x = FT_ABS( (FT_Short)value );
    568        }
    569 
    570        prop = bdf_get_font_property( font, "RESOLUTION_Y" );
    571        if ( prop )
    572          value = prop->value.l;
    573        else
    574          value = (long)font->resolution_y;
    575        if ( value )
    576        {
    577 #ifdef FT_DEBUG_LEVEL_TRACE
    578          if ( value < 0 )
    579            FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" ));
    580 #endif
    581          if ( value > 0x7FFF || value < -0x7FFF )
    582          {
    583            resolution_y = 0x7FFF;
    584            FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n",
    585                        resolution_y ));
    586          }
    587          else
    588            resolution_y = FT_ABS( (FT_Short)value );
    589        }
    590 
    591        if ( bsize->y_ppem == 0 )
    592        {
    593          bsize->y_ppem = bsize->size;
    594          if ( resolution_y )
    595            bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
    596        }
    597        if ( resolution_x && resolution_y )
    598          bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
    599                                     resolution_x,
    600                                     resolution_y );
    601        else
    602          bsize->x_ppem = bsize->y_ppem;
    603 
    604        prop = bdf_get_font_property( font, "DEFAULT_CHAR" );
    605        if ( prop )
    606          font->default_char = prop->value.ul;
    607        else
    608          font->default_char = ~0UL;
    609      }
    610 
    611      /* encoding table */
    612      {
    613        bdf_glyph_t*   cur = font->glyphs;
    614        unsigned long  n;
    615 
    616 
    617        if ( FT_QNEW_ARRAY( bdfface->en_table, font->glyphs_size ) )
    618          goto Exit;
    619 
    620        bdfface->default_glyph = 0;
    621        for ( n = 0; n < font->glyphs_size; n++ )
    622        {
    623          (bdfface->en_table[n]).enc = cur[n].encoding;
    624          FT_TRACE4(( "  idx %lu, val 0x%lX\n", n, cur[n].encoding ));
    625          (bdfface->en_table[n]).glyph = (FT_UShort)n;
    626 
    627          if ( cur[n].encoding == font->default_char )
    628          {
    629            if ( n < FT_UINT_MAX )
    630              bdfface->default_glyph = (FT_UInt)n;
    631            else
    632              FT_TRACE1(( "BDF_Face_Init:"
    633                          " idx %lu is too large for this system\n", n ));
    634          }
    635        }
    636      }
    637 
    638      /* charmaps */
    639      {
    640        bdf_property_t  *charset_registry, *charset_encoding;
    641        FT_Bool          unicode_charmap  = 0;
    642 
    643 
    644        charset_registry =
    645          bdf_get_font_property( font, "CHARSET_REGISTRY" );
    646        charset_encoding =
    647          bdf_get_font_property( font, "CHARSET_ENCODING" );
    648        if ( charset_registry && charset_encoding )
    649        {
    650          if ( charset_registry->format == BDF_ATOM &&
    651               charset_encoding->format == BDF_ATOM &&
    652               charset_registry->value.atom         &&
    653               charset_encoding->value.atom         )
    654          {
    655            const char*  s;
    656 
    657 
    658            if ( FT_STRDUP( bdfface->charset_encoding,
    659                            charset_encoding->value.atom ) ||
    660                 FT_STRDUP( bdfface->charset_registry,
    661                            charset_registry->value.atom ) )
    662              goto Exit;
    663 
    664            /* Uh, oh, compare first letters manually to avoid dependency */
    665            /* on locales.                                                */
    666            s = bdfface->charset_registry;
    667            if ( ( s[0] == 'i' || s[0] == 'I' ) &&
    668                 ( s[1] == 's' || s[1] == 'S' ) &&
    669                 ( s[2] == 'o' || s[2] == 'O' ) )
    670            {
    671              s += 3;
    672              if ( !ft_strcmp( s, "10646" )                         ||
    673                   ( !ft_strcmp( s, "8859" )                      &&
    674                     !ft_strcmp( bdfface->charset_encoding, "1" ) ) )
    675                unicode_charmap = 1;
    676              /* another name for ASCII */
    677              else if ( !ft_strcmp( s, "646.1991" )                    &&
    678                        !ft_strcmp( bdfface->charset_encoding, "IRV" ) )
    679                unicode_charmap = 1;
    680            }
    681 
    682            {
    683              FT_CharMapRec  charmap;
    684 
    685 
    686              charmap.face        = face;
    687              charmap.encoding    = FT_ENCODING_NONE;
    688              /* initial platform/encoding should indicate unset status? */
    689              charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
    690              charmap.encoding_id = TT_APPLE_ID_DEFAULT;
    691 
    692              if ( unicode_charmap )
    693              {
    694                charmap.encoding    = FT_ENCODING_UNICODE;
    695                charmap.platform_id = TT_PLATFORM_MICROSOFT;
    696                charmap.encoding_id = TT_MS_ID_UNICODE_CS;
    697              }
    698 
    699              error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
    700            }
    701 
    702            goto Exit;
    703          }
    704        }
    705 
    706        /* otherwise assume Adobe standard encoding */
    707 
    708        {
    709          FT_CharMapRec  charmap;
    710 
    711 
    712          charmap.face        = face;
    713          charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
    714          charmap.platform_id = TT_PLATFORM_ADOBE;
    715          charmap.encoding_id = TT_ADOBE_ID_STANDARD;
    716 
    717          error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
    718 
    719          /* Select default charmap */
    720          if ( face->num_charmaps )
    721            face->charmap = face->charmaps[0];
    722        }
    723      }
    724    }
    725 
    726  Exit:
    727    return error;
    728 
    729  Fail:
    730    BDF_Face_Done( face );
    731    return FT_THROW( Unknown_File_Format );
    732  }
    733 
    734 
    735  FT_CALLBACK_DEF( FT_Error )
    736  BDF_Size_Select( FT_Size   size,
    737                   FT_ULong  strike_index )
    738  {
    739    bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
    740 
    741 
    742    FT_Select_Metrics( size->face, strike_index );
    743 
    744    size->metrics.ascender    = bdffont->font_ascent * 64;
    745    size->metrics.descender   = -bdffont->font_descent * 64;
    746    size->metrics.max_advance = bdffont->bbx.width * 64;
    747 
    748    return FT_Err_Ok;
    749  }
    750 
    751 
    752  FT_CALLBACK_DEF( FT_Error )
    753  BDF_Size_Request( FT_Size          size,
    754                    FT_Size_Request  req )
    755  {
    756    FT_Face          face    = size->face;
    757    FT_Bitmap_Size*  bsize   = face->available_sizes;
    758    bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
    759    FT_Error         error   = FT_ERR( Invalid_Pixel_Size );
    760    FT_Long          height;
    761 
    762 
    763    height = FT_REQUEST_HEIGHT( req );
    764    height = ( height + 32 ) >> 6;
    765 
    766    switch ( req->type )
    767    {
    768    case FT_SIZE_REQUEST_TYPE_NOMINAL:
    769      if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
    770        error = FT_Err_Ok;
    771      break;
    772 
    773    case FT_SIZE_REQUEST_TYPE_REAL_DIM:
    774      if ( height == ( bdffont->font_ascent +
    775                       bdffont->font_descent ) )
    776        error = FT_Err_Ok;
    777      break;
    778 
    779    default:
    780      error = FT_THROW( Unimplemented_Feature );
    781      break;
    782    }
    783 
    784    if ( error )
    785      return error;
    786    else
    787      return BDF_Size_Select( size, 0 );
    788  }
    789 
    790 
    791 
    792  FT_CALLBACK_DEF( FT_Error )
    793  BDF_Glyph_Load( FT_GlyphSlot  slot,
    794                  FT_Size       size,
    795                  FT_UInt       glyph_index,
    796                  FT_Int32      load_flags )
    797  {
    798    FT_Face      face   = size->face;
    799    BDF_Face     bdf    = (BDF_Face)face;
    800    FT_Error     error  = FT_Err_Ok;
    801    FT_Bitmap*   bitmap = &slot->bitmap;
    802    bdf_glyph_t  glyph;
    803    int          bpp    = bdf->bdffont->bpp;
    804 
    805    FT_UNUSED( load_flags );
    806 
    807 
    808    if ( !face )
    809    {
    810      error = FT_THROW( Invalid_Face_Handle );
    811      goto Exit;
    812    }
    813 
    814    if ( glyph_index >= (FT_UInt)face->num_glyphs )
    815    {
    816      error = FT_THROW( Invalid_Argument );
    817      goto Exit;
    818    }
    819 
    820    FT_TRACE1(( "BDF_Glyph_Load: glyph index %u\n", glyph_index ));
    821 
    822    /* index 0 is the undefined glyph */
    823    if ( glyph_index == 0 )
    824      glyph_index = bdf->default_glyph;
    825    else
    826      glyph_index--;
    827 
    828    /* slot, bitmap => freetype, glyph => bdflib */
    829    glyph = bdf->bdffont->glyphs[glyph_index];
    830 
    831    bitmap->rows  = glyph.bbx.height;
    832    bitmap->width = glyph.bbx.width;
    833    if ( glyph.bpr > FT_INT_MAX )
    834      FT_TRACE1(( "BDF_Glyph_Load: too large pitch %lu is truncated\n",
    835                   glyph.bpr ));
    836    bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
    837 
    838    /* note: we don't allocate a new array to hold the bitmap; */
    839    /*       we can simply point to it                         */
    840    ft_glyphslot_set_bitmap( slot, glyph.bitmap );
    841 
    842    switch ( bpp )
    843    {
    844    case 1:
    845      bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
    846      break;
    847    case 2:
    848      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
    849      break;
    850    case 4:
    851      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
    852      break;
    853    case 8:
    854      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
    855      bitmap->num_grays  = 256;
    856      break;
    857    }
    858 
    859    slot->format      = FT_GLYPH_FORMAT_BITMAP;
    860    slot->bitmap_left = glyph.bbx.x_offset;
    861    slot->bitmap_top  = glyph.bbx.ascent;
    862 
    863    slot->metrics.horiAdvance  = (FT_Pos)( glyph.dwidth * 64 );
    864    slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 );
    865    slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 );
    866    slot->metrics.width        = (FT_Pos)( bitmap->width * 64 );
    867    slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
    868 
    869    /*
    870     * XXX DWIDTH1 and VVECTOR should be parsed and
    871     * used here, provided such fonts do exist.
    872     */
    873    ft_synthesize_vertical_metrics( &slot->metrics,
    874                                    bdf->bdffont->bbx.height * 64 );
    875 
    876  Exit:
    877    return error;
    878  }
    879 
    880 
    881 /*
    882  *
    883  * BDF SERVICE
    884  *
    885  */
    886 
    887  FT_CALLBACK_DEF( FT_Error )
    888  bdf_get_bdf_property( FT_Face           face,       /* BDF_Face */
    889                        const char*       prop_name,
    890                        BDF_PropertyRec  *aproperty )
    891  {
    892    BDF_Face         bdfface = (BDF_Face)face;
    893    bdf_property_t*  prop;
    894 
    895 
    896    FT_ASSERT( bdfface && bdfface->bdffont );
    897 
    898    prop = bdf_get_font_property( bdfface->bdffont, prop_name );
    899    if ( prop )
    900    {
    901      switch ( prop->format )
    902      {
    903      case BDF_ATOM:
    904        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
    905        aproperty->u.atom = prop->value.atom;
    906        break;
    907 
    908      case BDF_INTEGER:
    909        if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
    910        {
    911          FT_TRACE1(( "bdf_get_bdf_property:"
    912                      " too large integer 0x%lx is truncated\n",
    913                      prop->value.l ));
    914        }
    915        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
    916        aproperty->u.integer = (FT_Int32)prop->value.l;
    917        break;
    918 
    919      case BDF_CARDINAL:
    920        if ( prop->value.ul > 0xFFFFFFFFUL )
    921        {
    922          FT_TRACE1(( "bdf_get_bdf_property:"
    923                      " too large cardinal 0x%lx is truncated\n",
    924                      prop->value.ul ));
    925        }
    926        aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
    927        aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
    928        break;
    929 
    930      default:
    931        goto Fail;
    932      }
    933      return 0;
    934    }
    935 
    936  Fail:
    937    return FT_THROW( Invalid_Argument );
    938  }
    939 
    940 
    941  FT_CALLBACK_DEF( FT_Error )
    942  bdf_get_charset_id( FT_Face       face,               /* BDF_Face */
    943                      const char*  *acharset_encoding,
    944                      const char*  *acharset_registry )
    945  {
    946    BDF_Face  bdfface = (BDF_Face)face;
    947 
    948 
    949    *acharset_encoding = bdfface->charset_encoding;
    950    *acharset_registry = bdfface->charset_registry;
    951 
    952    return 0;
    953  }
    954 
    955 
    956  static const FT_Service_BDFRec  bdf_service_bdf =
    957  {
    958    (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,       /* get_charset_id */
    959    (FT_BDF_GetPropertyFunc) bdf_get_bdf_property      /* get_property   */
    960  };
    961 
    962 
    963 /*
    964  *
    965  * SERVICES LIST
    966  *
    967  */
    968 
    969  static const FT_ServiceDescRec  bdf_services[] =
    970  {
    971    { FT_SERVICE_ID_BDF,         &bdf_service_bdf },
    972    { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF },
    973    { NULL, NULL }
    974  };
    975 
    976 
    977  FT_CALLBACK_DEF( FT_Module_Interface )
    978  bdf_driver_requester( FT_Module    module,
    979                        const char*  name )
    980  {
    981    FT_UNUSED( module );
    982 
    983    return ft_service_list_lookup( bdf_services, name );
    984  }
    985 
    986 
    987  FT_CALLBACK_TABLE_DEF
    988  const FT_Driver_ClassRec  bdf_driver_class =
    989  {
    990    {
    991      FT_MODULE_FONT_DRIVER         |
    992      FT_MODULE_DRIVER_NO_OUTLINES,
    993      sizeof ( FT_DriverRec ),
    994 
    995      "bdf",
    996      0x10000L,
    997      0x20000L,
    998 
    999      NULL,    /* module-specific interface */
   1000 
   1001      NULL,                     /* FT_Module_Constructor  module_init   */
   1002      NULL,                     /* FT_Module_Destructor   module_done   */
   1003      bdf_driver_requester      /* FT_Module_Requester    get_interface */
   1004    },
   1005 
   1006    sizeof ( BDF_FaceRec ),
   1007    sizeof ( FT_SizeRec ),
   1008    sizeof ( FT_GlyphSlotRec ),
   1009 
   1010    BDF_Face_Init,              /* FT_Face_InitFunc  init_face */
   1011    BDF_Face_Done,              /* FT_Face_DoneFunc  done_face */
   1012    NULL,                       /* FT_Size_InitFunc  init_size */
   1013    NULL,                       /* FT_Size_DoneFunc  done_size */
   1014    NULL,                       /* FT_Slot_InitFunc  init_slot */
   1015    NULL,                       /* FT_Slot_DoneFunc  done_slot */
   1016 
   1017    BDF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
   1018 
   1019    NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
   1020    NULL,                       /* FT_Face_AttachFunc       attach_file  */
   1021    NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
   1022 
   1023    BDF_Size_Request,           /* FT_Size_RequestFunc  request_size */
   1024    BDF_Size_Select             /* FT_Size_SelectFunc   select_size  */
   1025  };
   1026 
   1027 
   1028 /* END */