tizen 2.3.1 release
[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, 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 #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 FT_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   static
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  = FT_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     for ( len = 0, nn = 0; nn < 4; nn++ )
247     {
248       lengths[nn] = 0;
249       if ( strings[nn] )
250       {
251         lengths[nn] = ft_strlen( strings[nn] );
252         len        += lengths[nn] + 1;
253       }
254     }
255
256     if ( len == 0 )
257     {
258       strings[0] = (char *)"Regular";
259       lengths[0] = ft_strlen( strings[0] );
260       len        = lengths[0] + 1;
261     }
262
263     {
264       char*  s;
265
266
267       if ( FT_ALLOC( face->style_name, len ) )
268         return error;
269
270       s = face->style_name;
271
272       for ( nn = 0; nn < 4; nn++ )
273       {
274         char*  src = strings[nn];
275
276
277         len = lengths[nn];
278
279         if ( src == NULL )
280           continue;
281
282         /* separate elements with a space */
283         if ( s != face->style_name )
284           *s++ = ' ';
285
286         ft_memcpy( s, src, len );
287
288         /* need to convert spaces to dashes for */
289         /* add_style_name and setwidth_name     */
290         if ( nn == 0 || nn == 3 )
291         {
292           size_t  mm;
293
294
295           for ( mm = 0; mm < len; mm++ )
296             if ( s[mm] == ' ' )
297               s[mm] = '-';
298         }
299
300         s += len;
301       }
302       *s = 0;
303     }
304
305     return error;
306   }
307
308
309   FT_CALLBACK_DEF( void )
310   BDF_Face_Done( FT_Face  bdfface )         /* BDF_Face */
311   {
312     BDF_Face   face = (BDF_Face)bdfface;
313     FT_Memory  memory;
314
315
316     if ( !face )
317       return;
318
319     memory = FT_FACE_MEMORY( face );
320
321     bdf_free_font( face->bdffont );
322
323     FT_FREE( face->en_table );
324
325     FT_FREE( face->charset_encoding );
326     FT_FREE( face->charset_registry );
327     FT_FREE( bdfface->family_name );
328     FT_FREE( bdfface->style_name );
329
330     FT_FREE( bdfface->available_sizes );
331
332     FT_FREE( face->bdffont );
333   }
334
335
336   FT_CALLBACK_DEF( FT_Error )
337   BDF_Face_Init( FT_Stream      stream,
338                  FT_Face        bdfface,        /* BDF_Face */
339                  FT_Int         face_index,
340                  FT_Int         num_params,
341                  FT_Parameter*  params )
342   {
343     FT_Error       error  = FT_Err_Ok;
344     BDF_Face       face   = (BDF_Face)bdfface;
345     FT_Memory      memory = FT_FACE_MEMORY( face );
346
347     bdf_font_t*    font = NULL;
348     bdf_options_t  options;
349
350     FT_UNUSED( num_params );
351     FT_UNUSED( params );
352
353
354     FT_TRACE2(( "BDF driver\n" ));
355
356     if ( FT_STREAM_SEEK( 0 ) )
357       goto Exit;
358
359     options.correct_metrics = 1;   /* FZ XXX: options semantics */
360     options.keep_unencoded  = 1;
361     options.keep_comments   = 0;
362     options.font_spacing    = BDF_PROPORTIONAL;
363
364     error = bdf_load_font( stream, memory, &options, &font );
365     if ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
366     {
367       FT_TRACE2(( "  not a BDF file\n" ));
368       goto Fail;
369     }
370     else if ( error )
371       goto Exit;
372
373     /* we have a bdf font: let's construct the face object */
374     face->bdffont = font;
375
376     /* BDF could not have multiple face in single font file.
377      * XXX: non-zero face_index is already invalid argument, but
378      *      Type1, Type42 driver has a convention to return
379      *      an invalid argument error when the font could be
380      *      opened by the specified driver.
381      */
382     if ( face_index > 0 ) {
383       FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
384       BDF_Face_Done( bdfface );
385       return FT_THROW( Invalid_Argument );
386     }
387
388     {
389       bdf_property_t*  prop = NULL;
390
391
392       FT_TRACE4(( "  number of glyphs: allocated %d (used %d)\n",
393                   font->glyphs_size,
394                   font->glyphs_used ));
395       FT_TRACE4(( "  number of unencoded glyphs: allocated %d (used %d)\n",
396                   font->unencoded_size,
397                   font->unencoded_used ));
398
399       bdfface->num_faces  = 1;
400       bdfface->face_index = 0;
401
402       bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
403                              FT_FACE_FLAG_HORIZONTAL  |
404                              FT_FACE_FLAG_FAST_GLYPHS;
405
406       prop = bdf_get_font_property( font, "SPACING" );
407       if ( prop && prop->format == BDF_ATOM                             &&
408            prop->value.atom                                             &&
409            ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
410              *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
411         bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
412
413       /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL   */
414       /* FZ XXX: I need a font to implement this */
415
416       prop = bdf_get_font_property( font, "FAMILY_NAME" );
417       if ( prop && prop->value.atom )
418       {
419         if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
420           goto Exit;
421       }
422       else
423         bdfface->family_name = 0;
424
425       if ( ( error = bdf_interpret_style( face ) ) != 0 )
426         goto Exit;
427
428       /* the number of glyphs (with one slot for the undefined glyph */
429       /* at position 0 and all unencoded glyphs)                     */
430       bdfface->num_glyphs = font->glyphs_size + 1;
431
432       bdfface->num_fixed_sizes = 1;
433       if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
434         goto Exit;
435
436       {
437         FT_Bitmap_Size*  bsize = bdfface->available_sizes;
438         FT_Short         resolution_x = 0, resolution_y = 0;
439
440
441         FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
442
443         bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
444
445         prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
446         if ( prop )
447           bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
448         else
449           bsize->width = (FT_Short)( bsize->height * 2/3 );
450
451         prop = bdf_get_font_property( font, "POINT_SIZE" );
452         if ( prop )
453           /* convert from 722.7 decipoints to 72 points per inch */
454           bsize->size =
455             (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
456         else
457           bsize->size = bsize->width << 6;
458
459         prop = bdf_get_font_property( font, "PIXEL_SIZE" );
460         if ( prop )
461           bsize->y_ppem = (FT_Short)prop->value.l << 6;
462
463         prop = bdf_get_font_property( font, "RESOLUTION_X" );
464         if ( prop )
465           resolution_x = (FT_Short)prop->value.l;
466
467         prop = bdf_get_font_property( font, "RESOLUTION_Y" );
468         if ( prop )
469           resolution_y = (FT_Short)prop->value.l;
470
471         if ( bsize->y_ppem == 0 )
472         {
473           bsize->y_ppem = bsize->size;
474           if ( resolution_y )
475             bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
476         }
477         if ( resolution_x && resolution_y )
478           bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
479         else
480           bsize->x_ppem = bsize->y_ppem;
481       }
482
483       /* encoding table */
484       {
485         bdf_glyph_t*   cur = font->glyphs;
486         unsigned long  n;
487
488
489         if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
490           goto Exit;
491
492         face->default_glyph = 0;
493         for ( n = 0; n < font->glyphs_size; n++ )
494         {
495           (face->en_table[n]).enc = cur[n].encoding;
496           FT_TRACE4(( "  idx %d, val 0x%lX\n", n, cur[n].encoding ));
497           (face->en_table[n]).glyph = (FT_Short)n;
498
499           if ( cur[n].encoding == font->default_char )
500           {
501             if ( n < FT_UINT_MAX )
502               face->default_glyph = (FT_UInt)n;
503             else
504               FT_TRACE1(( "BDF_Face_Init:"
505                           " idx %d is too large for this system\n", n ));
506           }
507         }
508       }
509
510       /* charmaps */
511       {
512         bdf_property_t  *charset_registry = 0, *charset_encoding = 0;
513         FT_Bool          unicode_charmap  = 0;
514
515
516         charset_registry =
517           bdf_get_font_property( font, "CHARSET_REGISTRY" );
518         charset_encoding =
519           bdf_get_font_property( font, "CHARSET_ENCODING" );
520         if ( charset_registry && charset_encoding )
521         {
522           if ( charset_registry->format == BDF_ATOM &&
523                charset_encoding->format == BDF_ATOM &&
524                charset_registry->value.atom         &&
525                charset_encoding->value.atom         )
526           {
527             const char*  s;
528
529
530             if ( FT_STRDUP( face->charset_encoding,
531                             charset_encoding->value.atom ) ||
532                  FT_STRDUP( face->charset_registry,
533                             charset_registry->value.atom ) )
534               goto Exit;
535
536             /* Uh, oh, compare first letters manually to avoid dependency */
537             /* on locales.                                                */
538             s = face->charset_registry;
539             if ( ( s[0] == 'i' || s[0] == 'I' ) &&
540                  ( s[1] == 's' || s[1] == 'S' ) &&
541                  ( s[2] == 'o' || s[2] == 'O' ) )
542             {
543               s += 3;
544               if ( !ft_strcmp( s, "10646" )                      ||
545                    ( !ft_strcmp( s, "8859" ) &&
546                      !ft_strcmp( face->charset_encoding, "1" ) ) )
547               unicode_charmap = 1;
548             }
549
550             {
551               FT_CharMapRec  charmap;
552
553
554               charmap.face        = FT_FACE( face );
555               charmap.encoding    = FT_ENCODING_NONE;
556               /* initial platform/encoding should indicate unset status? */
557               charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
558               charmap.encoding_id = TT_APPLE_ID_DEFAULT;
559
560               if ( unicode_charmap )
561               {
562                 charmap.encoding    = FT_ENCODING_UNICODE;
563                 charmap.platform_id = TT_PLATFORM_MICROSOFT;
564                 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
565               }
566
567               error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
568
569 #if 0
570               /* Select default charmap */
571               if ( bdfface->num_charmaps )
572                 bdfface->charmap = bdfface->charmaps[0];
573 #endif
574             }
575
576             goto Exit;
577           }
578         }
579
580         /* otherwise assume Adobe standard encoding */
581
582         {
583           FT_CharMapRec  charmap;
584
585
586           charmap.face        = FT_FACE( face );
587           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
588           charmap.platform_id = TT_PLATFORM_ADOBE;
589           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
590
591           error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
592
593           /* Select default charmap */
594           if ( bdfface->num_charmaps )
595             bdfface->charmap = bdfface->charmaps[0];
596         }
597       }
598     }
599
600   Exit:
601     return error;
602
603   Fail:
604     BDF_Face_Done( bdfface );
605     return FT_THROW( Unknown_File_Format );
606   }
607
608
609   FT_CALLBACK_DEF( FT_Error )
610   BDF_Size_Select( FT_Size   size,
611                    FT_ULong  strike_index )
612   {
613     bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
614
615
616     FT_Select_Metrics( size->face, strike_index );
617
618     size->metrics.ascender    = bdffont->font_ascent << 6;
619     size->metrics.descender   = -bdffont->font_descent << 6;
620     size->metrics.max_advance = bdffont->bbx.width << 6;
621
622     return FT_Err_Ok;
623   }
624
625
626   FT_CALLBACK_DEF( FT_Error )
627   BDF_Size_Request( FT_Size          size,
628                     FT_Size_Request  req )
629   {
630     FT_Face          face    = size->face;
631     FT_Bitmap_Size*  bsize   = face->available_sizes;
632     bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
633     FT_Error         error   = FT_ERR( Invalid_Pixel_Size );
634     FT_Long          height;
635
636
637     height = FT_REQUEST_HEIGHT( req );
638     height = ( height + 32 ) >> 6;
639
640     switch ( req->type )
641     {
642     case FT_SIZE_REQUEST_TYPE_NOMINAL:
643       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
644         error = FT_Err_Ok;
645       break;
646
647     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
648       if ( height == ( bdffont->font_ascent +
649                        bdffont->font_descent ) )
650         error = FT_Err_Ok;
651       break;
652
653     default:
654       error = FT_THROW( Unimplemented_Feature );
655       break;
656     }
657
658     if ( error )
659       return error;
660     else
661       return BDF_Size_Select( size, 0 );
662   }
663
664
665
666   FT_CALLBACK_DEF( FT_Error )
667   BDF_Glyph_Load( FT_GlyphSlot  slot,
668                   FT_Size       size,
669                   FT_UInt       glyph_index,
670                   FT_Int32      load_flags )
671   {
672     BDF_Face     bdf    = (BDF_Face)FT_SIZE_FACE( size );
673     FT_Face      face   = FT_FACE( bdf );
674     FT_Error     error  = FT_Err_Ok;
675     FT_Bitmap*   bitmap = &slot->bitmap;
676     bdf_glyph_t  glyph;
677     int          bpp    = bdf->bdffont->bpp;
678
679     FT_UNUSED( load_flags );
680
681
682     if ( !face )
683     {
684       error = FT_THROW( Invalid_Face_Handle );
685       goto Exit;
686     }
687
688     if ( glyph_index >= (FT_UInt)face->num_glyphs )
689     {
690       error = FT_THROW( Invalid_Argument );
691       goto Exit;
692     }
693
694     FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
695
696     /* index 0 is the undefined glyph */
697     if ( glyph_index == 0 )
698       glyph_index = bdf->default_glyph;
699     else
700       glyph_index--;
701
702     /* slot, bitmap => freetype, glyph => bdflib */
703     glyph = bdf->bdffont->glyphs[glyph_index];
704
705     bitmap->rows  = glyph.bbx.height;
706     bitmap->width = glyph.bbx.width;
707     if ( glyph.bpr > INT_MAX )
708       FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
709                    glyph.bpr ));
710     bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
711
712     /* note: we don't allocate a new array to hold the bitmap; */
713     /*       we can simply point to it                         */
714     ft_glyphslot_set_bitmap( slot, glyph.bitmap );
715
716     switch ( bpp )
717     {
718     case 1:
719       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
720       break;
721     case 2:
722       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
723       break;
724     case 4:
725       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
726       break;
727     case 8:
728       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
729       bitmap->num_grays  = 256;
730       break;
731     }
732
733     slot->format      = FT_GLYPH_FORMAT_BITMAP;
734     slot->bitmap_left = glyph.bbx.x_offset;
735     slot->bitmap_top  = glyph.bbx.ascent;
736
737     slot->metrics.horiAdvance  = glyph.dwidth << 6;
738     slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
739     slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
740     slot->metrics.width        = bitmap->width << 6;
741     slot->metrics.height       = bitmap->rows << 6;
742
743     /*
744      * XXX DWIDTH1 and VVECTOR should be parsed and
745      * used here, provided such fonts do exist.
746      */
747     ft_synthesize_vertical_metrics( &slot->metrics,
748                                     bdf->bdffont->bbx.height << 6 );
749
750   Exit:
751     return error;
752   }
753
754
755  /*
756   *
757   *  BDF SERVICE
758   *
759   */
760
761   static FT_Error
762   bdf_get_bdf_property( BDF_Face          face,
763                         const char*       prop_name,
764                         BDF_PropertyRec  *aproperty )
765   {
766     bdf_property_t*  prop;
767
768
769     FT_ASSERT( face && face->bdffont );
770
771     prop = bdf_get_font_property( face->bdffont, prop_name );
772     if ( prop )
773     {
774       switch ( prop->format )
775       {
776       case BDF_ATOM:
777         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
778         aproperty->u.atom = prop->value.atom;
779         break;
780
781       case BDF_INTEGER:
782         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
783         {
784           FT_TRACE1(( "bdf_get_bdf_property:"
785                       " too large integer 0x%x is truncated\n" ));
786         }
787         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
788         aproperty->u.integer = (FT_Int32)prop->value.l;
789         break;
790
791       case BDF_CARDINAL:
792         if ( prop->value.ul > 0xFFFFFFFFUL )
793         {
794           FT_TRACE1(( "bdf_get_bdf_property:"
795                       " too large cardinal 0x%x is truncated\n" ));
796         }
797         aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
798         aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
799         break;
800
801       default:
802         goto Fail;
803       }
804       return 0;
805     }
806
807   Fail:
808     return FT_THROW( Invalid_Argument );
809   }
810
811
812   static FT_Error
813   bdf_get_charset_id( BDF_Face      face,
814                       const char*  *acharset_encoding,
815                       const char*  *acharset_registry )
816   {
817     *acharset_encoding = face->charset_encoding;
818     *acharset_registry = face->charset_registry;
819
820     return 0;
821   }
822
823
824   static const FT_Service_BDFRec  bdf_service_bdf =
825   {
826     (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
827     (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
828   };
829
830
831  /*
832   *
833   *  SERVICES LIST
834   *
835   */
836
837   static const FT_ServiceDescRec  bdf_services[] =
838   {
839     { FT_SERVICE_ID_BDF,       &bdf_service_bdf },
840     { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
841     { NULL, NULL }
842   };
843
844
845   FT_CALLBACK_DEF( FT_Module_Interface )
846   bdf_driver_requester( FT_Module    module,
847                         const char*  name )
848   {
849     FT_UNUSED( module );
850
851     return ft_service_list_lookup( bdf_services, name );
852   }
853
854
855
856   FT_CALLBACK_TABLE_DEF
857   const FT_Driver_ClassRec  bdf_driver_class =
858   {
859     {
860       FT_MODULE_FONT_DRIVER         |
861       FT_MODULE_DRIVER_NO_OUTLINES,
862       sizeof ( FT_DriverRec ),
863
864       "bdf",
865       0x10000L,
866       0x20000L,
867
868       0,
869
870       0,                        /* FT_Module_Constructor */
871       0,                        /* FT_Module_Destructor  */
872       bdf_driver_requester
873     },
874
875     sizeof ( BDF_FaceRec ),
876     sizeof ( FT_SizeRec ),
877     sizeof ( FT_GlyphSlotRec ),
878
879     BDF_Face_Init,
880     BDF_Face_Done,
881     0,                          /* FT_Size_InitFunc */
882     0,                          /* FT_Size_DoneFunc */
883     0,                          /* FT_Slot_InitFunc */
884     0,                          /* FT_Slot_DoneFunc */
885
886     BDF_Glyph_Load,
887
888     0,                          /* FT_Face_GetKerningFunc  */
889     0,                          /* FT_Face_AttachFunc      */
890     0,                          /* FT_Face_GetAdvancesFunc */
891
892     BDF_Size_Request,
893     BDF_Size_Select
894   };
895
896
897 /* END */