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