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 )
bdf_cmap_init(FT_CMap bdfcmap,FT_Pointer init_data)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 )
bdf_cmap_done(FT_CMap bdfcmap)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 )
bdf_cmap_char_index(FT_CMap bdfcmap,FT_UInt32 charcode)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 )
bdf_cmap_char_next(FT_CMap bdfcmap,FT_UInt32 * acharcode)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
bdf_interpret_style(BDF_Face bdf)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 )
BDF_Face_Done(FT_Face bdfface)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 )
BDF_Face_Init(FT_Stream stream,FT_Face bdfface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)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 )
BDF_Size_Select(FT_Size size,FT_ULong strike_index)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 )
BDF_Size_Request(FT_Size size,FT_Size_Request req)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 )
BDF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)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 || glyph_index >= (FT_UInt)face->num_glyphs )
683     {
684       error = FT_THROW( Invalid_Argument );
685       goto Exit;
686     }
687 
688     FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
689 
690     /* index 0 is the undefined glyph */
691     if ( glyph_index == 0 )
692       glyph_index = bdf->default_glyph;
693     else
694       glyph_index--;
695 
696     /* slot, bitmap => freetype, glyph => bdflib */
697     glyph = bdf->bdffont->glyphs[glyph_index];
698 
699     bitmap->rows  = glyph.bbx.height;
700     bitmap->width = glyph.bbx.width;
701     if ( glyph.bpr > INT_MAX )
702       FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
703                    glyph.bpr ));
704     bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
705 
706     /* note: we don't allocate a new array to hold the bitmap; */
707     /*       we can simply point to it                         */
708     ft_glyphslot_set_bitmap( slot, glyph.bitmap );
709 
710     switch ( bpp )
711     {
712     case 1:
713       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
714       break;
715     case 2:
716       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
717       break;
718     case 4:
719       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
720       break;
721     case 8:
722       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
723       bitmap->num_grays  = 256;
724       break;
725     }
726 
727     slot->format      = FT_GLYPH_FORMAT_BITMAP;
728     slot->bitmap_left = glyph.bbx.x_offset;
729     slot->bitmap_top  = glyph.bbx.ascent;
730 
731     slot->metrics.horiAdvance  = glyph.dwidth << 6;
732     slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
733     slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
734     slot->metrics.width        = bitmap->width << 6;
735     slot->metrics.height       = bitmap->rows << 6;
736 
737     /*
738      * XXX DWIDTH1 and VVECTOR should be parsed and
739      * used here, provided such fonts do exist.
740      */
741     ft_synthesize_vertical_metrics( &slot->metrics,
742                                     bdf->bdffont->bbx.height << 6 );
743 
744   Exit:
745     return error;
746   }
747 
748 
749  /*
750   *
751   *  BDF SERVICE
752   *
753   */
754 
755   static FT_Error
bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)756   bdf_get_bdf_property( BDF_Face          face,
757                         const char*       prop_name,
758                         BDF_PropertyRec  *aproperty )
759   {
760     bdf_property_t*  prop;
761 
762 
763     FT_ASSERT( face && face->bdffont );
764 
765     prop = bdf_get_font_property( face->bdffont, prop_name );
766     if ( prop )
767     {
768       switch ( prop->format )
769       {
770       case BDF_ATOM:
771         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
772         aproperty->u.atom = prop->value.atom;
773         break;
774 
775       case BDF_INTEGER:
776         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
777         {
778           FT_TRACE1(( "bdf_get_bdf_property:"
779                       " too large integer 0x%x is truncated\n" ));
780         }
781         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
782         aproperty->u.integer = (FT_Int32)prop->value.l;
783         break;
784 
785       case BDF_CARDINAL:
786         if ( prop->value.ul > 0xFFFFFFFFUL )
787         {
788           FT_TRACE1(( "bdf_get_bdf_property:"
789                       " too large cardinal 0x%x is truncated\n" ));
790         }
791         aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
792         aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
793         break;
794 
795       default:
796         goto Fail;
797       }
798       return 0;
799     }
800 
801   Fail:
802     return FT_THROW( Invalid_Argument );
803   }
804 
805 
806   static FT_Error
bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)807   bdf_get_charset_id( BDF_Face      face,
808                       const char*  *acharset_encoding,
809                       const char*  *acharset_registry )
810   {
811     *acharset_encoding = face->charset_encoding;
812     *acharset_registry = face->charset_registry;
813 
814     return 0;
815   }
816 
817 
818   static const FT_Service_BDFRec  bdf_service_bdf =
819   {
820     (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
821     (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
822   };
823 
824 
825  /*
826   *
827   *  SERVICES LIST
828   *
829   */
830 
831   static const FT_ServiceDescRec  bdf_services[] =
832   {
833     { FT_SERVICE_ID_BDF,       &bdf_service_bdf },
834     { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
835     { NULL, NULL }
836   };
837 
838 
839   FT_CALLBACK_DEF( FT_Module_Interface )
bdf_driver_requester(FT_Module module,const char * name)840   bdf_driver_requester( FT_Module    module,
841                         const char*  name )
842   {
843     FT_UNUSED( module );
844 
845     return ft_service_list_lookup( bdf_services, name );
846   }
847 
848 
849 
850   FT_CALLBACK_TABLE_DEF
851   const FT_Driver_ClassRec  bdf_driver_class =
852   {
853     {
854       FT_MODULE_FONT_DRIVER         |
855       FT_MODULE_DRIVER_NO_OUTLINES,
856       sizeof ( FT_DriverRec ),
857 
858       "bdf",
859       0x10000L,
860       0x20000L,
861 
862       0,
863 
864       0,                        /* FT_Module_Constructor */
865       0,                        /* FT_Module_Destructor  */
866       bdf_driver_requester
867     },
868 
869     sizeof ( BDF_FaceRec ),
870     sizeof ( FT_SizeRec ),
871     sizeof ( FT_GlyphSlotRec ),
872 
873     BDF_Face_Init,
874     BDF_Face_Done,
875     0,                          /* FT_Size_InitFunc */
876     0,                          /* FT_Size_DoneFunc */
877     0,                          /* FT_Slot_InitFunc */
878     0,                          /* FT_Slot_DoneFunc */
879 
880     BDF_Glyph_Load,
881 
882     0,                          /* FT_Face_GetKerningFunc  */
883     0,                          /* FT_Face_AttachFunc      */
884     0,                          /* FT_Face_GetAdvancesFunc */
885 
886     BDF_Size_Request,
887     BDF_Size_Select
888   };
889 
890 
891 /* END */
892