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   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
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 )
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
bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)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
bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)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 )
bdf_driver_requester(FT_Module module,const char * name)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 */
898