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_FONT_FORMAT_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 = (FT_ULong)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 = (FT_ULong)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 = (FT_ULong)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 )
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 && ( face_index & 0xFFFF ) > 0 )
383     {
384       FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
385       BDF_Face_Done( bdfface );
386       return FT_THROW( Invalid_Argument );
387     }
388 
389     {
390       bdf_property_t*  prop = NULL;
391 
392 
393       FT_TRACE4(( "  number of glyphs: allocated %d (used %d)\n",
394                   font->glyphs_size,
395                   font->glyphs_used ));
396       FT_TRACE4(( "  number of unencoded glyphs: allocated %d (used %d)\n",
397                   font->unencoded_size,
398                   font->unencoded_used ));
399 
400       bdfface->num_faces  = 1;
401       bdfface->face_index = 0;
402 
403       bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
404                              FT_FACE_FLAG_HORIZONTAL  |
405                              FT_FACE_FLAG_FAST_GLYPHS;
406 
407       prop = bdf_get_font_property( font, "SPACING" );
408       if ( prop && prop->format == BDF_ATOM                             &&
409            prop->value.atom                                             &&
410            ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
411              *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
412         bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
413 
414       /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL   */
415       /* FZ XXX: I need a font to implement this */
416 
417       prop = bdf_get_font_property( font, "FAMILY_NAME" );
418       if ( prop && prop->value.atom )
419       {
420         if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
421           goto Exit;
422       }
423       else
424         bdfface->family_name = NULL;
425 
426       if ( FT_SET_ERROR( bdf_interpret_style( face ) ) )
427         goto Exit;
428 
429       /* the number of glyphs (with one slot for the undefined glyph */
430       /* at position 0 and all unencoded glyphs)                     */
431       bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 );
432 
433       bdfface->num_fixed_sizes = 1;
434       if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
435         goto Exit;
436 
437       {
438         FT_Bitmap_Size*  bsize = bdfface->available_sizes;
439         FT_Short         resolution_x = 0, resolution_y = 0;
440 
441 
442         FT_ZERO( bsize );
443 
444         bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
445 
446         prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
447         if ( prop )
448           bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
449         else
450           bsize->width = (FT_Short)( bsize->height * 2/3 );
451 
452         prop = bdf_get_font_property( font, "POINT_SIZE" );
453         if ( prop )
454           /* convert from 722.7 decipoints to 72 points per inch */
455           bsize->size =
456             (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
457         else
458           bsize->size = bsize->width << 6;
459 
460         prop = bdf_get_font_property( font, "PIXEL_SIZE" );
461         if ( prop )
462           bsize->y_ppem = (FT_Short)prop->value.l << 6;
463 
464         prop = bdf_get_font_property( font, "RESOLUTION_X" );
465         if ( prop )
466           resolution_x = (FT_Short)prop->value.l;
467 
468         prop = bdf_get_font_property( font, "RESOLUTION_Y" );
469         if ( prop )
470           resolution_y = (FT_Short)prop->value.l;
471 
472         if ( bsize->y_ppem == 0 )
473         {
474           bsize->y_ppem = bsize->size;
475           if ( resolution_y )
476             bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
477         }
478         if ( resolution_x && resolution_y )
479           bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
480         else
481           bsize->x_ppem = bsize->y_ppem;
482       }
483 
484       /* encoding table */
485       {
486         bdf_glyph_t*   cur = font->glyphs;
487         unsigned long  n;
488 
489 
490         if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
491           goto Exit;
492 
493         face->default_glyph = 0;
494         for ( n = 0; n < font->glyphs_size; n++ )
495         {
496           (face->en_table[n]).enc = cur[n].encoding;
497           FT_TRACE4(( "  idx %d, val 0x%lX\n", n, cur[n].encoding ));
498           (face->en_table[n]).glyph = (FT_UShort)n;
499 
500           if ( cur[n].encoding == font->default_char )
501           {
502             if ( n < FT_UINT_MAX )
503               face->default_glyph = (FT_UInt)n;
504             else
505               FT_TRACE1(( "BDF_Face_Init:"
506                           " idx %d is too large for this system\n", n ));
507           }
508         }
509       }
510 
511       /* charmaps */
512       {
513         bdf_property_t  *charset_registry, *charset_encoding;
514         FT_Bool          unicode_charmap  = 0;
515 
516 
517         charset_registry =
518           bdf_get_font_property( font, "CHARSET_REGISTRY" );
519         charset_encoding =
520           bdf_get_font_property( font, "CHARSET_ENCODING" );
521         if ( charset_registry && charset_encoding )
522         {
523           if ( charset_registry->format == BDF_ATOM &&
524                charset_encoding->format == BDF_ATOM &&
525                charset_registry->value.atom         &&
526                charset_encoding->value.atom         )
527           {
528             const char*  s;
529 
530 
531             if ( FT_STRDUP( face->charset_encoding,
532                             charset_encoding->value.atom ) ||
533                  FT_STRDUP( face->charset_registry,
534                             charset_registry->value.atom ) )
535               goto Exit;
536 
537             /* Uh, oh, compare first letters manually to avoid dependency */
538             /* on locales.                                                */
539             s = face->charset_registry;
540             if ( ( s[0] == 'i' || s[0] == 'I' ) &&
541                  ( s[1] == 's' || s[1] == 'S' ) &&
542                  ( s[2] == 'o' || s[2] == 'O' ) )
543             {
544               s += 3;
545               if ( !ft_strcmp( s, "10646" )                      ||
546                    ( !ft_strcmp( s, "8859" ) &&
547                      !ft_strcmp( face->charset_encoding, "1" ) ) )
548               unicode_charmap = 1;
549             }
550 
551             {
552               FT_CharMapRec  charmap;
553 
554 
555               charmap.face        = FT_FACE( face );
556               charmap.encoding    = FT_ENCODING_NONE;
557               /* initial platform/encoding should indicate unset status? */
558               charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
559               charmap.encoding_id = TT_APPLE_ID_DEFAULT;
560 
561               if ( unicode_charmap )
562               {
563                 charmap.encoding    = FT_ENCODING_UNICODE;
564                 charmap.platform_id = TT_PLATFORM_MICROSOFT;
565                 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
566               }
567 
568               error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
569 
570 #if 0
571               /* Select default charmap */
572               if ( bdfface->num_charmaps )
573                 bdfface->charmap = bdfface->charmaps[0];
574 #endif
575             }
576 
577             goto Exit;
578           }
579         }
580 
581         /* otherwise assume Adobe standard encoding */
582 
583         {
584           FT_CharMapRec  charmap;
585 
586 
587           charmap.face        = FT_FACE( face );
588           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
589           charmap.platform_id = TT_PLATFORM_ADOBE;
590           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
591 
592           error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
593 
594           /* Select default charmap */
595           if ( bdfface->num_charmaps )
596             bdfface->charmap = bdfface->charmaps[0];
597         }
598       }
599     }
600 
601   Exit:
602     return error;
603 
604   Fail:
605     BDF_Face_Done( bdfface );
606     return FT_THROW( Unknown_File_Format );
607   }
608 
609 
610   FT_CALLBACK_DEF( FT_Error )
BDF_Size_Select(FT_Size size,FT_ULong strike_index)611   BDF_Size_Select( FT_Size   size,
612                    FT_ULong  strike_index )
613   {
614     bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
615 
616 
617     FT_Select_Metrics( size->face, strike_index );
618 
619     size->metrics.ascender    = bdffont->font_ascent * 64;
620     size->metrics.descender   = -bdffont->font_descent * 64;
621     size->metrics.max_advance = bdffont->bbx.width * 64;
622 
623     return FT_Err_Ok;
624   }
625 
626 
627   FT_CALLBACK_DEF( FT_Error )
BDF_Size_Request(FT_Size size,FT_Size_Request req)628   BDF_Size_Request( FT_Size          size,
629                     FT_Size_Request  req )
630   {
631     FT_Face          face    = size->face;
632     FT_Bitmap_Size*  bsize   = face->available_sizes;
633     bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
634     FT_Error         error   = FT_ERR( Invalid_Pixel_Size );
635     FT_Long          height;
636 
637 
638     height = FT_REQUEST_HEIGHT( req );
639     height = ( height + 32 ) >> 6;
640 
641     switch ( req->type )
642     {
643     case FT_SIZE_REQUEST_TYPE_NOMINAL:
644       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
645         error = FT_Err_Ok;
646       break;
647 
648     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
649       if ( height == ( bdffont->font_ascent +
650                        bdffont->font_descent ) )
651         error = FT_Err_Ok;
652       break;
653 
654     default:
655       error = FT_THROW( Unimplemented_Feature );
656       break;
657     }
658 
659     if ( error )
660       return error;
661     else
662       return BDF_Size_Select( size, 0 );
663   }
664 
665 
666 
667   FT_CALLBACK_DEF( FT_Error )
BDF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)668   BDF_Glyph_Load( FT_GlyphSlot  slot,
669                   FT_Size       size,
670                   FT_UInt       glyph_index,
671                   FT_Int32      load_flags )
672   {
673     BDF_Face     bdf    = (BDF_Face)FT_SIZE_FACE( size );
674     FT_Face      face   = FT_FACE( bdf );
675     FT_Error     error  = FT_Err_Ok;
676     FT_Bitmap*   bitmap = &slot->bitmap;
677     bdf_glyph_t  glyph;
678     int          bpp    = bdf->bdffont->bpp;
679 
680     FT_UNUSED( load_flags );
681 
682 
683     if ( !face )
684     {
685       error = FT_THROW( Invalid_Face_Handle );
686       goto Exit;
687     }
688 
689     if ( glyph_index >= (FT_UInt)face->num_glyphs )
690     {
691       error = FT_THROW( Invalid_Argument );
692       goto Exit;
693     }
694 
695     FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
696 
697     /* index 0 is the undefined glyph */
698     if ( glyph_index == 0 )
699       glyph_index = bdf->default_glyph;
700     else
701       glyph_index--;
702 
703     /* slot, bitmap => freetype, glyph => bdflib */
704     glyph = bdf->bdffont->glyphs[glyph_index];
705 
706     bitmap->rows  = glyph.bbx.height;
707     bitmap->width = glyph.bbx.width;
708     if ( glyph.bpr > INT_MAX )
709       FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
710                    glyph.bpr ));
711     bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
712 
713     /* note: we don't allocate a new array to hold the bitmap; */
714     /*       we can simply point to it                         */
715     ft_glyphslot_set_bitmap( slot, glyph.bitmap );
716 
717     switch ( bpp )
718     {
719     case 1:
720       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
721       break;
722     case 2:
723       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
724       break;
725     case 4:
726       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
727       break;
728     case 8:
729       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
730       bitmap->num_grays  = 256;
731       break;
732     }
733 
734     slot->format      = FT_GLYPH_FORMAT_BITMAP;
735     slot->bitmap_left = glyph.bbx.x_offset;
736     slot->bitmap_top  = glyph.bbx.ascent;
737 
738     slot->metrics.horiAdvance  = (FT_Pos)( glyph.dwidth * 64 );
739     slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 );
740     slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 );
741     slot->metrics.width        = (FT_Pos)( bitmap->width * 64 );
742     slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
743 
744     /*
745      * XXX DWIDTH1 and VVECTOR should be parsed and
746      * used here, provided such fonts do exist.
747      */
748     ft_synthesize_vertical_metrics( &slot->metrics,
749                                     bdf->bdffont->bbx.height * 64 );
750 
751   Exit:
752     return error;
753   }
754 
755 
756  /*
757   *
758   *  BDF SERVICE
759   *
760   */
761 
762   static FT_Error
bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)763   bdf_get_bdf_property( BDF_Face          face,
764                         const char*       prop_name,
765                         BDF_PropertyRec  *aproperty )
766   {
767     bdf_property_t*  prop;
768 
769 
770     FT_ASSERT( face && face->bdffont );
771 
772     prop = bdf_get_font_property( face->bdffont, prop_name );
773     if ( prop )
774     {
775       switch ( prop->format )
776       {
777       case BDF_ATOM:
778         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
779         aproperty->u.atom = prop->value.atom;
780         break;
781 
782       case BDF_INTEGER:
783         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
784         {
785           FT_TRACE1(( "bdf_get_bdf_property:"
786                       " too large integer 0x%x is truncated\n" ));
787         }
788         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
789         aproperty->u.integer = (FT_Int32)prop->value.l;
790         break;
791 
792       case BDF_CARDINAL:
793         if ( prop->value.ul > 0xFFFFFFFFUL )
794         {
795           FT_TRACE1(( "bdf_get_bdf_property:"
796                       " too large cardinal 0x%x is truncated\n" ));
797         }
798         aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
799         aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
800         break;
801 
802       default:
803         goto Fail;
804       }
805       return 0;
806     }
807 
808   Fail:
809     return FT_THROW( Invalid_Argument );
810   }
811 
812 
813   static FT_Error
bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)814   bdf_get_charset_id( BDF_Face      face,
815                       const char*  *acharset_encoding,
816                       const char*  *acharset_registry )
817   {
818     *acharset_encoding = face->charset_encoding;
819     *acharset_registry = face->charset_registry;
820 
821     return 0;
822   }
823 
824 
825   static const FT_Service_BDFRec  bdf_service_bdf =
826   {
827     (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,       /* get_charset_id */
828     (FT_BDF_GetPropertyFunc) bdf_get_bdf_property      /* get_property   */
829   };
830 
831 
832  /*
833   *
834   *  SERVICES LIST
835   *
836   */
837 
838   static const FT_ServiceDescRec  bdf_services[] =
839   {
840     { FT_SERVICE_ID_BDF,         &bdf_service_bdf },
841     { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF },
842     { NULL, NULL }
843   };
844 
845 
846   FT_CALLBACK_DEF( FT_Module_Interface )
bdf_driver_requester(FT_Module module,const char * name)847   bdf_driver_requester( FT_Module    module,
848                         const char*  name )
849   {
850     FT_UNUSED( module );
851 
852     return ft_service_list_lookup( bdf_services, name );
853   }
854 
855 
856 
857   FT_CALLBACK_TABLE_DEF
858   const FT_Driver_ClassRec  bdf_driver_class =
859   {
860     {
861       FT_MODULE_FONT_DRIVER         |
862       FT_MODULE_DRIVER_NO_OUTLINES,
863       sizeof ( FT_DriverRec ),
864 
865       "bdf",
866       0x10000L,
867       0x20000L,
868 
869       NULL,    /* module-specific interface */
870 
871       NULL,                     /* FT_Module_Constructor  module_init   */
872       NULL,                     /* FT_Module_Destructor   module_done   */
873       bdf_driver_requester      /* FT_Module_Requester    get_interface */
874     },
875 
876     sizeof ( BDF_FaceRec ),
877     sizeof ( FT_SizeRec ),
878     sizeof ( FT_GlyphSlotRec ),
879 
880     BDF_Face_Init,              /* FT_Face_InitFunc  init_face */
881     BDF_Face_Done,              /* FT_Face_DoneFunc  done_face */
882     NULL,                       /* FT_Size_InitFunc  init_size */
883     NULL,                       /* FT_Size_DoneFunc  done_size */
884     NULL,                       /* FT_Slot_InitFunc  init_slot */
885     NULL,                       /* FT_Slot_DoneFunc  done_slot */
886 
887     BDF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
888 
889     NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
890     NULL,                       /* FT_Face_AttachFunc       attach_file  */
891     NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
892 
893     BDF_Size_Request,           /* FT_Size_RequestFunc  request_size */
894     BDF_Size_Select             /* FT_Size_SelectFunc   select_size  */
895   };
896 
897 
898 /* END */
899