Initialize Tizen 2.3
[framework/graphics/freetype.git] / src / bdf / bdfdrivr.c
1 /*  bdfdrivr.c
2
3     FreeType font driver for bdf files
4
5     Copyright (C) 2001-2008, 2011 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
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 */