(root)/
freetype-2.13.2/
src/
bdf/
bdfdrivr.c
       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      bdf_options_t  options;
     353  
     354      FT_UNUSED( num_params );
     355      FT_UNUSED( params );
     356  
     357  
     358      FT_TRACE2(( "BDF driver\n" ));
     359  
     360      if ( FT_STREAM_SEEK( 0 ) )
     361        goto Exit;
     362  
     363      options.correct_metrics = 1;   /* FZ XXX: options semantics */
     364      options.keep_unencoded  = 1;
     365      options.keep_comments   = 0;
     366      options.font_spacing    = BDF_PROPORTIONAL;
     367  
     368      error = bdf_load_font( stream, memory, &options, &font );
     369      if ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
     370      {
     371        FT_TRACE2(( "  not a BDF file\n" ));
     372        goto Fail;
     373      }
     374      else if ( error )
     375        goto Exit;
     376  
     377      /* we have a bdf font: let's construct the face object */
     378      bdfface->bdffont = font;
     379  
     380      /* BDF cannot have multiple faces in a single font file.
     381       * XXX: non-zero face_index is already invalid argument, but
     382       *      Type1, Type42 driver has a convention to return
     383       *      an invalid argument error when the font could be
     384       *      opened by the specified driver.
     385       */
     386      if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
     387      {
     388        FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
     389        BDF_Face_Done( face );
     390        return FT_THROW( Invalid_Argument );
     391      }
     392  
     393      {
     394        bdf_property_t*  prop = NULL;
     395  
     396  
     397        FT_TRACE4(( "  number of glyphs: allocated %ld (used %ld)\n",
     398                    font->glyphs_size,
     399                    font->glyphs_used ));
     400        FT_TRACE4(( "  number of unencoded glyphs: allocated %ld (used %ld)\n",
     401                    font->unencoded_size,
     402                    font->unencoded_used ));
     403  
     404        face->num_faces  = 1;
     405        face->face_index = 0;
     406  
     407        face->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
     408                            FT_FACE_FLAG_HORIZONTAL;
     409  
     410        prop = bdf_get_font_property( font, "SPACING" );
     411        if ( prop && prop->format == BDF_ATOM                             &&
     412             prop->value.atom                                             &&
     413             ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
     414               *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
     415          face->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
     416  
     417        /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL   */
     418        /* FZ XXX: I need a font to implement this */
     419  
     420        prop = bdf_get_font_property( font, "FAMILY_NAME" );
     421        if ( prop && prop->value.atom )
     422        {
     423          if ( FT_STRDUP( face->family_name, prop->value.atom ) )
     424            goto Exit;
     425        }
     426        else
     427          face->family_name = NULL;
     428  
     429        if ( FT_SET_ERROR( bdf_interpret_style( bdfface ) ) )
     430          goto Exit;
     431  
     432        /* the number of glyphs (with one slot for the undefined glyph */
     433        /* at position 0 and all unencoded glyphs)                     */
     434        face->num_glyphs = (FT_Long)( font->glyphs_size + 1 );
     435  
     436        face->num_fixed_sizes = 1;
     437        if ( FT_NEW( face->available_sizes ) )
     438          goto Exit;
     439  
     440        {
     441          FT_Bitmap_Size*  bsize        = face->available_sizes;
     442          FT_Short         resolution_x = 0;
     443          FT_Short         resolution_y = 0;
     444          long             value;
     445  
     446  
     447          /* sanity checks */
     448          if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF )
     449          {
     450            font->font_ascent = font->font_ascent < 0 ? -0x7FFF : 0x7FFF;
     451            FT_TRACE0(( "BDF_Face_Init: clamping font ascent to value %ld\n",
     452                        font->font_ascent ));
     453          }
     454          if ( font->font_descent > 0x7FFF || font->font_descent < -0x7FFF )
     455          {
     456            font->font_descent = font->font_descent < 0 ? -0x7FFF : 0x7FFF;
     457            FT_TRACE0(( "BDF_Face_Init: clamping font descent to value %ld\n",
     458                        font->font_descent ));
     459          }
     460  
     461          bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
     462  
     463          prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
     464          if ( prop )
     465          {
     466  #ifdef FT_DEBUG_LEVEL_TRACE
     467            if ( prop->value.l < 0 )
     468              FT_TRACE0(( "BDF_Face_Init: negative average width\n" ));
     469  #endif
     470            if ( prop->value.l >    0x7FFFL * 10 - 5   ||
     471                 prop->value.l < -( 0x7FFFL * 10 - 5 ) )
     472            {
     473              bsize->width = 0x7FFF;
     474              FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n",
     475                          bsize->width ));
     476            }
     477            else
     478              bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
     479          }
     480          else
     481          {
     482            /* this is a heuristical value */
     483            bsize->width = ( bsize->height * 2 + 1 ) / 3;
     484          }
     485  
     486          prop = bdf_get_font_property( font, "POINT_SIZE" );
     487          if ( prop )
     488          {
     489  #ifdef FT_DEBUG_LEVEL_TRACE
     490            if ( prop->value.l < 0 )
     491              FT_TRACE0(( "BDF_Face_Init: negative point size\n" ));
     492  #endif
     493            /* convert from 722.7 decipoints to 72 points per inch */
     494            if ( prop->value.l >  0x504C2L || /* 0x7FFF * 72270/7200 */
     495                 prop->value.l < -0x504C2L )
     496            {
     497              bsize->size = 0x7FFF;
     498              FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
     499                          bsize->size ));
     500            }
     501            else
     502              bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
     503                                       64 * 7200,
     504                                       72270L );
     505          }
     506          else if ( font->point_size )
     507          {
     508            if ( font->point_size > 0x7FFF )
     509            {
     510              bsize->size = 0x7FFF;
     511              FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
     512                          bsize->size ));
     513            }
     514            else
     515              bsize->size = (FT_Pos)font->point_size << 6;
     516          }
     517          else
     518          {
     519            /* this is a heuristical value */
     520            bsize->size = bsize->width * 64;
     521          }
     522  
     523          prop = bdf_get_font_property( font, "PIXEL_SIZE" );
     524          if ( prop )
     525          {
     526  #ifdef FT_DEBUG_LEVEL_TRACE
     527            if ( prop->value.l < 0 )
     528              FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" ));
     529  #endif
     530            if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF )
     531            {
     532              bsize->y_ppem = 0x7FFF << 6;
     533              FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %ld\n",
     534                          bsize->y_ppem ));
     535            }
     536            else
     537              bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
     538          }
     539  
     540          prop = bdf_get_font_property( font, "RESOLUTION_X" );
     541          if ( prop )
     542            value = prop->value.l;
     543          else
     544            value = (long)font->resolution_x;
     545          if ( value )
     546          {
     547  #ifdef FT_DEBUG_LEVEL_TRACE
     548            if ( value < 0 )
     549              FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" ));
     550  #endif
     551            if ( value > 0x7FFF || value < -0x7FFF )
     552            {
     553              resolution_x = 0x7FFF;
     554              FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n",
     555                          resolution_x ));
     556            }
     557            else
     558              resolution_x = FT_ABS( (FT_Short)value );
     559          }
     560  
     561          prop = bdf_get_font_property( font, "RESOLUTION_Y" );
     562          if ( prop )
     563            value = prop->value.l;
     564          else
     565            value = (long)font->resolution_y;
     566          if ( value )
     567          {
     568  #ifdef FT_DEBUG_LEVEL_TRACE
     569            if ( value < 0 )
     570              FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" ));
     571  #endif
     572            if ( value > 0x7FFF || value < -0x7FFF )
     573            {
     574              resolution_y = 0x7FFF;
     575              FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n",
     576                          resolution_y ));
     577            }
     578            else
     579              resolution_y = FT_ABS( (FT_Short)value );
     580          }
     581  
     582          if ( bsize->y_ppem == 0 )
     583          {
     584            bsize->y_ppem = bsize->size;
     585            if ( resolution_y )
     586              bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
     587          }
     588          if ( resolution_x && resolution_y )
     589            bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
     590                                       resolution_x,
     591                                       resolution_y );
     592          else
     593            bsize->x_ppem = bsize->y_ppem;
     594        }
     595  
     596        /* encoding table */
     597        {
     598          bdf_glyph_t*   cur = font->glyphs;
     599          unsigned long  n;
     600  
     601  
     602          if ( FT_QNEW_ARRAY( bdfface->en_table, font->glyphs_size ) )
     603            goto Exit;
     604  
     605          bdfface->default_glyph = 0;
     606          for ( n = 0; n < font->glyphs_size; n++ )
     607          {
     608            (bdfface->en_table[n]).enc = cur[n].encoding;
     609            FT_TRACE4(( "  idx %ld, val 0x%lX\n", n, cur[n].encoding ));
     610            (bdfface->en_table[n]).glyph = (FT_UShort)n;
     611  
     612            if ( cur[n].encoding == font->default_char )
     613            {
     614              if ( n < FT_UINT_MAX )
     615                bdfface->default_glyph = (FT_UInt)n;
     616              else
     617                FT_TRACE1(( "BDF_Face_Init:"
     618                            " idx %ld is too large for this system\n", n ));
     619            }
     620          }
     621        }
     622  
     623        /* charmaps */
     624        {
     625          bdf_property_t  *charset_registry, *charset_encoding;
     626          FT_Bool          unicode_charmap  = 0;
     627  
     628  
     629          charset_registry =
     630            bdf_get_font_property( font, "CHARSET_REGISTRY" );
     631          charset_encoding =
     632            bdf_get_font_property( font, "CHARSET_ENCODING" );
     633          if ( charset_registry && charset_encoding )
     634          {
     635            if ( charset_registry->format == BDF_ATOM &&
     636                 charset_encoding->format == BDF_ATOM &&
     637                 charset_registry->value.atom         &&
     638                 charset_encoding->value.atom         )
     639            {
     640              const char*  s;
     641  
     642  
     643              if ( FT_STRDUP( bdfface->charset_encoding,
     644                              charset_encoding->value.atom ) ||
     645                   FT_STRDUP( bdfface->charset_registry,
     646                              charset_registry->value.atom ) )
     647                goto Exit;
     648  
     649              /* Uh, oh, compare first letters manually to avoid dependency */
     650              /* on locales.                                                */
     651              s = bdfface->charset_registry;
     652              if ( ( s[0] == 'i' || s[0] == 'I' ) &&
     653                   ( s[1] == 's' || s[1] == 'S' ) &&
     654                   ( s[2] == 'o' || s[2] == 'O' ) )
     655              {
     656                s += 3;
     657                if ( !ft_strcmp( s, "10646" )                         ||
     658                     ( !ft_strcmp( s, "8859" )                      &&
     659                       !ft_strcmp( bdfface->charset_encoding, "1" ) ) )
     660                  unicode_charmap = 1;
     661                /* another name for ASCII */
     662                else if ( !ft_strcmp( s, "646.1991" )                    &&
     663                          !ft_strcmp( bdfface->charset_encoding, "IRV" ) )
     664                  unicode_charmap = 1;
     665              }
     666  
     667              {
     668                FT_CharMapRec  charmap;
     669  
     670  
     671                charmap.face        = face;
     672                charmap.encoding    = FT_ENCODING_NONE;
     673                /* initial platform/encoding should indicate unset status? */
     674                charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
     675                charmap.encoding_id = TT_APPLE_ID_DEFAULT;
     676  
     677                if ( unicode_charmap )
     678                {
     679                  charmap.encoding    = FT_ENCODING_UNICODE;
     680                  charmap.platform_id = TT_PLATFORM_MICROSOFT;
     681                  charmap.encoding_id = TT_MS_ID_UNICODE_CS;
     682                }
     683  
     684                error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
     685              }
     686  
     687              goto Exit;
     688            }
     689          }
     690  
     691          /* otherwise assume Adobe standard encoding */
     692  
     693          {
     694            FT_CharMapRec  charmap;
     695  
     696  
     697            charmap.face        = face;
     698            charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
     699            charmap.platform_id = TT_PLATFORM_ADOBE;
     700            charmap.encoding_id = TT_ADOBE_ID_STANDARD;
     701  
     702            error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
     703  
     704            /* Select default charmap */
     705            if ( face->num_charmaps )
     706              face->charmap = face->charmaps[0];
     707          }
     708        }
     709      }
     710  
     711    Exit:
     712      return error;
     713  
     714    Fail:
     715      BDF_Face_Done( face );
     716      return FT_THROW( Unknown_File_Format );
     717    }
     718  
     719  
     720    FT_CALLBACK_DEF( FT_Error )
     721    BDF_Size_Select( FT_Size   size,
     722                     FT_ULong  strike_index )
     723    {
     724      bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
     725  
     726  
     727      FT_Select_Metrics( size->face, strike_index );
     728  
     729      size->metrics.ascender    = bdffont->font_ascent * 64;
     730      size->metrics.descender   = -bdffont->font_descent * 64;
     731      size->metrics.max_advance = bdffont->bbx.width * 64;
     732  
     733      return FT_Err_Ok;
     734    }
     735  
     736  
     737    FT_CALLBACK_DEF( FT_Error )
     738    BDF_Size_Request( FT_Size          size,
     739                      FT_Size_Request  req )
     740    {
     741      FT_Face          face    = size->face;
     742      FT_Bitmap_Size*  bsize   = face->available_sizes;
     743      bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
     744      FT_Error         error   = FT_ERR( Invalid_Pixel_Size );
     745      FT_Long          height;
     746  
     747  
     748      height = FT_REQUEST_HEIGHT( req );
     749      height = ( height + 32 ) >> 6;
     750  
     751      switch ( req->type )
     752      {
     753      case FT_SIZE_REQUEST_TYPE_NOMINAL:
     754        if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
     755          error = FT_Err_Ok;
     756        break;
     757  
     758      case FT_SIZE_REQUEST_TYPE_REAL_DIM:
     759        if ( height == ( bdffont->font_ascent +
     760                         bdffont->font_descent ) )
     761          error = FT_Err_Ok;
     762        break;
     763  
     764      default:
     765        error = FT_THROW( Unimplemented_Feature );
     766        break;
     767      }
     768  
     769      if ( error )
     770        return error;
     771      else
     772        return BDF_Size_Select( size, 0 );
     773    }
     774  
     775  
     776  
     777    FT_CALLBACK_DEF( FT_Error )
     778    BDF_Glyph_Load( FT_GlyphSlot  slot,
     779                    FT_Size       size,
     780                    FT_UInt       glyph_index,
     781                    FT_Int32      load_flags )
     782    {
     783      BDF_Face     bdf    = (BDF_Face)FT_SIZE_FACE( size );
     784      FT_Face      face   = FT_FACE( bdf );
     785      FT_Error     error  = FT_Err_Ok;
     786      FT_Bitmap*   bitmap = &slot->bitmap;
     787      bdf_glyph_t  glyph;
     788      int          bpp    = bdf->bdffont->bpp;
     789  
     790      FT_UNUSED( load_flags );
     791  
     792  
     793      if ( !face )
     794      {
     795        error = FT_THROW( Invalid_Face_Handle );
     796        goto Exit;
     797      }
     798  
     799      if ( glyph_index >= (FT_UInt)face->num_glyphs )
     800      {
     801        error = FT_THROW( Invalid_Argument );
     802        goto Exit;
     803      }
     804  
     805      FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
     806  
     807      /* index 0 is the undefined glyph */
     808      if ( glyph_index == 0 )
     809        glyph_index = bdf->default_glyph;
     810      else
     811        glyph_index--;
     812  
     813      /* slot, bitmap => freetype, glyph => bdflib */
     814      glyph = bdf->bdffont->glyphs[glyph_index];
     815  
     816      bitmap->rows  = glyph.bbx.height;
     817      bitmap->width = glyph.bbx.width;
     818      if ( glyph.bpr > FT_INT_MAX )
     819        FT_TRACE1(( "BDF_Glyph_Load: too large pitch %ld is truncated\n",
     820                     glyph.bpr ));
     821      bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
     822  
     823      /* note: we don't allocate a new array to hold the bitmap; */
     824      /*       we can simply point to it                         */
     825      ft_glyphslot_set_bitmap( slot, glyph.bitmap );
     826  
     827      switch ( bpp )
     828      {
     829      case 1:
     830        bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
     831        break;
     832      case 2:
     833        bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
     834        break;
     835      case 4:
     836        bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
     837        break;
     838      case 8:
     839        bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
     840        bitmap->num_grays  = 256;
     841        break;
     842      }
     843  
     844      slot->format      = FT_GLYPH_FORMAT_BITMAP;
     845      slot->bitmap_left = glyph.bbx.x_offset;
     846      slot->bitmap_top  = glyph.bbx.ascent;
     847  
     848      slot->metrics.horiAdvance  = (FT_Pos)( glyph.dwidth * 64 );
     849      slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 );
     850      slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 );
     851      slot->metrics.width        = (FT_Pos)( bitmap->width * 64 );
     852      slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
     853  
     854      /*
     855       * XXX DWIDTH1 and VVECTOR should be parsed and
     856       * used here, provided such fonts do exist.
     857       */
     858      ft_synthesize_vertical_metrics( &slot->metrics,
     859                                      bdf->bdffont->bbx.height * 64 );
     860  
     861    Exit:
     862      return error;
     863    }
     864  
     865  
     866   /*
     867    *
     868    * BDF SERVICE
     869    *
     870    */
     871  
     872    FT_CALLBACK_DEF( FT_Error )
     873    bdf_get_bdf_property( FT_Face           face,       /* BDF_Face */
     874                          const char*       prop_name,
     875                          BDF_PropertyRec  *aproperty )
     876    {
     877      BDF_Face         bdfface = (BDF_Face)face;
     878      bdf_property_t*  prop;
     879  
     880  
     881      FT_ASSERT( bdfface && bdfface->bdffont );
     882  
     883      prop = bdf_get_font_property( bdfface->bdffont, prop_name );
     884      if ( prop )
     885      {
     886        switch ( prop->format )
     887        {
     888        case BDF_ATOM:
     889          aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
     890          aproperty->u.atom = prop->value.atom;
     891          break;
     892  
     893        case BDF_INTEGER:
     894          if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
     895          {
     896            FT_TRACE1(( "bdf_get_bdf_property:"
     897                        " too large integer 0x%lx is truncated\n",
     898                        prop->value.l ));
     899          }
     900          aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
     901          aproperty->u.integer = (FT_Int32)prop->value.l;
     902          break;
     903  
     904        case BDF_CARDINAL:
     905          if ( prop->value.ul > 0xFFFFFFFFUL )
     906          {
     907            FT_TRACE1(( "bdf_get_bdf_property:"
     908                        " too large cardinal 0x%lx is truncated\n",
     909                        prop->value.ul ));
     910          }
     911          aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
     912          aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
     913          break;
     914  
     915        default:
     916          goto Fail;
     917        }
     918        return 0;
     919      }
     920  
     921    Fail:
     922      return FT_THROW( Invalid_Argument );
     923    }
     924  
     925  
     926    FT_CALLBACK_DEF( FT_Error )
     927    bdf_get_charset_id( FT_Face       face,               /* BDF_Face */
     928                        const char*  *acharset_encoding,
     929                        const char*  *acharset_registry )
     930    {
     931      BDF_Face  bdfface = (BDF_Face)face;
     932  
     933  
     934      *acharset_encoding = bdfface->charset_encoding;
     935      *acharset_registry = bdfface->charset_registry;
     936  
     937      return 0;
     938    }
     939  
     940  
     941    static const FT_Service_BDFRec  bdf_service_bdf =
     942    {
     943      (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,       /* get_charset_id */
     944      (FT_BDF_GetPropertyFunc) bdf_get_bdf_property      /* get_property   */
     945    };
     946  
     947  
     948   /*
     949    *
     950    * SERVICES LIST
     951    *
     952    */
     953  
     954    static const FT_ServiceDescRec  bdf_services[] =
     955    {
     956      { FT_SERVICE_ID_BDF,         &bdf_service_bdf },
     957      { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF },
     958      { NULL, NULL }
     959    };
     960  
     961  
     962    FT_CALLBACK_DEF( FT_Module_Interface )
     963    bdf_driver_requester( FT_Module    module,
     964                          const char*  name )
     965    {
     966      FT_UNUSED( module );
     967  
     968      return ft_service_list_lookup( bdf_services, name );
     969    }
     970  
     971  
     972    FT_CALLBACK_TABLE_DEF
     973    const FT_Driver_ClassRec  bdf_driver_class =
     974    {
     975      {
     976        FT_MODULE_FONT_DRIVER         |
     977        FT_MODULE_DRIVER_NO_OUTLINES,
     978        sizeof ( FT_DriverRec ),
     979  
     980        "bdf",
     981        0x10000L,
     982        0x20000L,
     983  
     984        NULL,    /* module-specific interface */
     985  
     986        NULL,                     /* FT_Module_Constructor  module_init   */
     987        NULL,                     /* FT_Module_Destructor   module_done   */
     988        bdf_driver_requester      /* FT_Module_Requester    get_interface */
     989      },
     990  
     991      sizeof ( BDF_FaceRec ),
     992      sizeof ( FT_SizeRec ),
     993      sizeof ( FT_GlyphSlotRec ),
     994  
     995      BDF_Face_Init,              /* FT_Face_InitFunc  init_face */
     996      BDF_Face_Done,              /* FT_Face_DoneFunc  done_face */
     997      NULL,                       /* FT_Size_InitFunc  init_size */
     998      NULL,                       /* FT_Size_DoneFunc  done_size */
     999      NULL,                       /* FT_Slot_InitFunc  init_slot */
    1000      NULL,                       /* FT_Slot_DoneFunc  done_slot */
    1001  
    1002      BDF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
    1003  
    1004      NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
    1005      NULL,                       /* FT_Face_AttachFunc       attach_file  */
    1006      NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
    1007  
    1008      BDF_Size_Request,           /* FT_Size_RequestFunc  request_size */
    1009      BDF_Size_Select             /* FT_Size_SelectFunc   select_size  */
    1010    };
    1011  
    1012  
    1013  /* END */