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