PageRenderTime 58ms CodeModel.GetById 10ms app.highlight 41ms RepoModel.GetById 2ms app.codeStats 0ms

/src/freetype/src/bdf/bdfdrivr.c

https://bitbucket.org/cabalistic/ogredeps/
C | 882 lines | 612 code | 198 blank | 72 comment | 133 complexity | 6aa349dc9713a43163d841935443c175 MD5 | raw file
  1/*  bdfdrivr.c
  2
  3    FreeType font driver for bdf files
  4
  5    Copyright (C) 2001-2008, 2011 by
  6    Francesco Zappa Nardelli
  7
  8Permission is hereby granted, free of charge, to any person obtaining a copy
  9of this software and associated documentation files (the "Software"), to deal
 10in the Software without restriction, including without limitation the rights
 11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12copies of the Software, and to permit persons to whom the Software is
 13furnished to do so, subject to the following conditions:
 14
 15The above copyright notice and this permission notice shall be included in
 16all copies or substantial portions of the Software.
 17
 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24THE 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
337
338  FT_CALLBACK_DEF( FT_Error )
339  BDF_Face_Init( FT_Stream      stream,
340                 FT_Face        bdfface,        /* BDF_Face */
341                 FT_Int         face_index,
342                 FT_Int         num_params,
343                 FT_Parameter*  params )
344  {
345    FT_Error       error  = BDF_Err_Ok;
346    BDF_Face       face   = (BDF_Face)bdfface;
347    FT_Memory      memory = FT_FACE_MEMORY( face );
348
349    bdf_font_t*    font = NULL;
350    bdf_options_t  options;
351
352    FT_UNUSED( num_params );
353    FT_UNUSED( params );
354    FT_UNUSED( face_index );
355
356
357    FT_TRACE2(( "BDF driver\n" ));
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 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: allocated %d (used %d)\n",
383                  font->glyphs_size,
384                  font->glyphs_used ));
385      FT_TRACE4(( "  number of unencoded glyphs: allocated %d (used %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(( "BDF_Face_Init:"
494                          " idx %d is too large for this system\n", n ));
495          }
496        }
497      }
498
499      /* charmaps */
500      {
501        bdf_property_t  *charset_registry = 0, *charset_encoding = 0;
502        FT_Bool          unicode_charmap  = 0;
503
504
505        charset_registry =
506          bdf_get_font_property( font, "CHARSET_REGISTRY" );
507        charset_encoding =
508          bdf_get_font_property( font, "CHARSET_ENCODING" );
509        if ( charset_registry && charset_encoding )
510        {
511          if ( charset_registry->format == BDF_ATOM &&
512               charset_encoding->format == BDF_ATOM &&
513               charset_registry->value.atom         &&
514               charset_encoding->value.atom         )
515          {
516            const char*  s;
517
518
519            if ( FT_STRDUP( face->charset_encoding,
520                            charset_encoding->value.atom ) ||
521                 FT_STRDUP( face->charset_registry,
522                            charset_registry->value.atom ) )
523              goto Exit;
524
525            /* Uh, oh, compare first letters manually to avoid dependency */
526            /* on locales.                                                */
527            s = face->charset_registry;
528            if ( ( s[0] == 'i' || s[0] == 'I' ) &&
529                 ( s[1] == 's' || s[1] == 'S' ) &&
530                 ( s[2] == 'o' || s[2] == 'O' ) )
531            {
532              s += 3;
533              if ( !ft_strcmp( s, "10646" )                      ||
534                   ( !ft_strcmp( s, "8859" ) &&
535                     !ft_strcmp( face->charset_encoding, "1" ) ) )
536              unicode_charmap = 1;
537            }
538
539            {
540              FT_CharMapRec  charmap;
541
542
543              charmap.face        = FT_FACE( face );
544              charmap.encoding    = FT_ENCODING_NONE;
545              /* initial platform/encoding should indicate unset status? */
546              charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
547              charmap.encoding_id = TT_APPLE_ID_DEFAULT;
548
549              if ( unicode_charmap )
550              {
551                charmap.encoding    = FT_ENCODING_UNICODE;
552                charmap.platform_id = TT_PLATFORM_MICROSOFT;
553                charmap.encoding_id = TT_MS_ID_UNICODE_CS;
554              }
555
556              error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
557
558#if 0
559              /* Select default charmap */
560              if ( bdfface->num_charmaps )
561                bdfface->charmap = bdfface->charmaps[0];
562#endif
563            }
564
565            goto Exit;
566          }
567        }
568
569        /* otherwise assume Adobe standard encoding */
570
571        {
572          FT_CharMapRec  charmap;
573
574
575          charmap.face        = FT_FACE( face );
576          charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
577          charmap.platform_id = TT_PLATFORM_ADOBE;
578          charmap.encoding_id = TT_ADOBE_ID_STANDARD;
579
580          error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
581
582          /* Select default charmap */
583          if ( bdfface->num_charmaps )
584            bdfface->charmap = bdfface->charmaps[0];
585        }
586      }
587    }
588
589  Exit:
590    return error;
591
592  Fail:
593    BDF_Face_Done( bdfface );
594    return BDF_Err_Unknown_File_Format;
595  }
596
597
598  FT_CALLBACK_DEF( FT_Error )
599  BDF_Size_Select( FT_Size   size,
600                   FT_ULong  strike_index )
601  {
602    bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
603
604
605    FT_Select_Metrics( size->face, strike_index );
606
607    size->metrics.ascender    = bdffont->font_ascent << 6;
608    size->metrics.descender   = -bdffont->font_descent << 6;
609    size->metrics.max_advance = bdffont->bbx.width << 6;
610
611    return BDF_Err_Ok;
612  }
613
614
615  FT_CALLBACK_DEF( FT_Error )
616  BDF_Size_Request( FT_Size          size,
617                    FT_Size_Request  req )
618  {
619    FT_Face          face    = size->face;
620    FT_Bitmap_Size*  bsize   = face->available_sizes;
621    bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
622    FT_Error         error   = BDF_Err_Invalid_Pixel_Size;
623    FT_Long          height;
624
625
626    height = FT_REQUEST_HEIGHT( req );
627    height = ( height + 32 ) >> 6;
628
629    switch ( req->type )
630    {
631    case FT_SIZE_REQUEST_TYPE_NOMINAL:
632      if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
633        error = BDF_Err_Ok;
634      break;
635
636    case FT_SIZE_REQUEST_TYPE_REAL_DIM:
637      if ( height == ( bdffont->font_ascent +
638                       bdffont->font_descent ) )
639        error = BDF_Err_Ok;
640      break;
641
642    default:
643      error = BDF_Err_Unimplemented_Feature;
644      break;
645    }
646
647    if ( error )
648      return error;
649    else
650      return BDF_Size_Select( size, 0 );
651  }
652
653
654
655  FT_CALLBACK_DEF( FT_Error )
656  BDF_Glyph_Load( FT_GlyphSlot  slot,
657                  FT_Size       size,
658                  FT_UInt       glyph_index,
659                  FT_Int32      load_flags )
660  {
661    BDF_Face     bdf    = (BDF_Face)FT_SIZE_FACE( size );
662    FT_Face      face   = FT_FACE( bdf );
663    FT_Error     error  = BDF_Err_Ok;
664    FT_Bitmap*   bitmap = &slot->bitmap;
665    bdf_glyph_t  glyph;
666    int          bpp    = bdf->bdffont->bpp;
667
668    FT_UNUSED( load_flags );
669
670
671    if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
672    {
673      error = BDF_Err_Invalid_Argument;
674      goto Exit;
675    }
676
677    /* index 0 is the undefined glyph */
678    if ( glyph_index == 0 )
679      glyph_index = bdf->default_glyph;
680    else
681      glyph_index--;
682
683    /* slot, bitmap => freetype, glyph => bdflib */
684    glyph = bdf->bdffont->glyphs[glyph_index];
685
686    bitmap->rows  = glyph.bbx.height;
687    bitmap->width = glyph.bbx.width;
688    if ( glyph.bpr > INT_MAX )
689      FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
690                   glyph.bpr ));
691    bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
692
693    /* note: we don't allocate a new array to hold the bitmap; */
694    /*       we can simply point to it                         */
695    ft_glyphslot_set_bitmap( slot, glyph.bitmap );
696
697    switch ( bpp )
698    {
699    case 1:
700      bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
701      break;
702    case 2:
703      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
704      break;
705    case 4:
706      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
707      break;
708    case 8:
709      bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
710      bitmap->num_grays  = 256;
711      break;
712    }
713
714    slot->format      = FT_GLYPH_FORMAT_BITMAP;
715    slot->bitmap_left = glyph.bbx.x_offset;
716    slot->bitmap_top  = glyph.bbx.ascent;
717
718    slot->metrics.horiAdvance  = glyph.dwidth << 6;
719    slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
720    slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
721    slot->metrics.width        = bitmap->width << 6;
722    slot->metrics.height       = bitmap->rows << 6;
723
724    /*
725     * XXX DWIDTH1 and VVECTOR should be parsed and
726     * used here, provided such fonts do exist.
727     */
728    ft_synthesize_vertical_metrics( &slot->metrics,
729                                    bdf->bdffont->bbx.height << 6 );
730
731  Exit:
732    return error;
733  }
734
735
736 /*
737  *
738  *  BDF SERVICE
739  *
740  */
741
742  static FT_Error
743  bdf_get_bdf_property( BDF_Face          face,
744                        const char*       prop_name,
745                        BDF_PropertyRec  *aproperty )
746  {
747    bdf_property_t*  prop;
748
749
750    FT_ASSERT( face && face->bdffont );
751
752    prop = bdf_get_font_property( face->bdffont, prop_name );
753    if ( prop )
754    {
755      switch ( prop->format )
756      {
757      case BDF_ATOM:
758        aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
759        aproperty->u.atom = prop->value.atom;
760        break;
761
762      case BDF_INTEGER:
763        if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
764        {
765          FT_TRACE1(( "bdf_get_bdf_property:"
766                      " too large integer 0x%x is truncated\n" ));
767        }
768        aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
769        aproperty->u.integer = (FT_Int32)prop->value.l;
770        break;
771
772      case BDF_CARDINAL:
773        if ( prop->value.ul > 0xFFFFFFFFUL )
774        {
775          FT_TRACE1(( "bdf_get_bdf_property:"
776                      " too large cardinal 0x%x is truncated\n" ));
777        }
778        aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
779        aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
780        break;
781
782      default:
783        goto Fail;
784      }
785      return 0;
786    }
787
788  Fail:
789    return BDF_Err_Invalid_Argument;
790  }
791
792
793  static FT_Error
794  bdf_get_charset_id( BDF_Face      face,
795                      const char*  *acharset_encoding,
796                      const char*  *acharset_registry )
797  {
798    *acharset_encoding = face->charset_encoding;
799    *acharset_registry = face->charset_registry;
800
801    return 0;
802  }
803
804
805  static const FT_Service_BDFRec  bdf_service_bdf =
806  {
807    (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
808    (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
809  };
810
811
812 /*
813  *
814  *  SERVICES LIST
815  *
816  */
817
818  static const FT_ServiceDescRec  bdf_services[] =
819  {
820    { FT_SERVICE_ID_BDF,       &bdf_service_bdf },
821    { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
822    { NULL, NULL }
823  };
824
825
826  FT_CALLBACK_DEF( FT_Module_Interface )
827  bdf_driver_requester( FT_Module    module,
828                        const char*  name )
829  {
830    FT_UNUSED( module );
831
832    return ft_service_list_lookup( bdf_services, name );
833  }
834
835
836
837  FT_CALLBACK_TABLE_DEF
838  const FT_Driver_ClassRec  bdf_driver_class =
839  {
840    {
841      FT_MODULE_FONT_DRIVER         |
842      FT_MODULE_DRIVER_NO_OUTLINES,
843      sizeof ( FT_DriverRec ),
844
845      "bdf",
846      0x10000L,
847      0x20000L,
848
849      0,
850
851      0,                        /* FT_Module_Constructor */
852      0,                        /* FT_Module_Destructor  */
853      bdf_driver_requester
854    },
855
856    sizeof ( BDF_FaceRec ),
857    sizeof ( FT_SizeRec ),
858    sizeof ( FT_GlyphSlotRec ),
859
860    BDF_Face_Init,
861    BDF_Face_Done,
862    0,                          /* FT_Size_InitFunc */
863    0,                          /* FT_Size_DoneFunc */
864    0,                          /* FT_Slot_InitFunc */
865    0,                          /* FT_Slot_DoneFunc */
866
867#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
868    ft_stub_set_char_sizes,
869    ft_stub_set_pixel_sizes,
870#endif
871    BDF_Glyph_Load,
872
873    0,                          /* FT_Face_GetKerningFunc  */
874    0,                          /* FT_Face_AttachFunc      */
875    0,                          /* FT_Face_GetAdvancesFunc */
876
877    BDF_Size_Request,
878    BDF_Size_Select
879  };
880
881
882/* END */