• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 cannot have multiple faces in a 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 
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 = NULL;
424 
425       if ( FT_SET_ERROR( bdf_interpret_style( face ) ) )
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 = (FT_Long)( 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         long             value;
440 
441 
442         FT_ZERO( bsize );
443 
444         /* sanity checks */
445         if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF )
446         {
447           font->font_ascent = font->font_ascent < 0 ? -0x7FFF : 0x7FFF;
448           FT_TRACE0(( "BDF_Face_Init: clamping font ascent to value %d\n",
449                       font->font_ascent ));
450         }
451         if ( font->font_descent > 0x7FFF || font->font_descent < -0x7FFF )
452         {
453           font->font_descent = font->font_descent < 0 ? -0x7FFF : 0x7FFF;
454           FT_TRACE0(( "BDF_Face_Init: clamping font descent to value %d\n",
455                       font->font_descent ));
456         }
457 
458         bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
459 
460         prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
461         if ( prop )
462         {
463 #ifdef FT_DEBUG_LEVEL_TRACE
464           if ( prop->value.l < 0 )
465             FT_TRACE0(( "BDF_Face_Init: negative average width\n" ));
466 #endif
467           if ( prop->value.l >    0x7FFFL * 10 - 5   ||
468                prop->value.l < -( 0x7FFFL * 10 - 5 ) )
469           {
470             bsize->width = 0x7FFF;
471             FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n",
472                         bsize->width ));
473           }
474           else
475             bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
476         }
477         else
478         {
479           /* this is a heuristical value */
480           bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 );
481         }
482 
483         prop = bdf_get_font_property( font, "POINT_SIZE" );
484         if ( prop )
485         {
486 #ifdef FT_DEBUG_LEVEL_TRACE
487           if ( prop->value.l < 0 )
488             FT_TRACE0(( "BDF_Face_Init: negative point size\n" ));
489 #endif
490           /* convert from 722.7 decipoints to 72 points per inch */
491           if ( prop->value.l >  0x504C2L || /* 0x7FFF * 72270/7200 */
492                prop->value.l < -0x504C2L )
493           {
494             bsize->size = 0x7FFF;
495             FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n",
496                         bsize->size ));
497           }
498           else
499             bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
500                                      64 * 7200,
501                                      72270L );
502         }
503         else if ( font->point_size )
504         {
505           if ( font->point_size > 0x7FFF )
506           {
507             bsize->size = 0x7FFF;
508             FT_TRACE0(( "BDF_Face_Init: clamping point size to value %d\n",
509                         bsize->size ));
510           }
511           else
512             bsize->size = (FT_Pos)font->point_size << 6;
513         }
514         else
515         {
516           /* this is a heuristical value */
517           bsize->size = bsize->width * 64;
518         }
519 
520         prop = bdf_get_font_property( font, "PIXEL_SIZE" );
521         if ( prop )
522         {
523 #ifdef FT_DEBUG_LEVEL_TRACE
524           if ( prop->value.l < 0 )
525             FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" ));
526 #endif
527           if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF )
528           {
529             bsize->y_ppem = 0x7FFF << 6;
530             FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %d\n",
531                         bsize->y_ppem ));
532           }
533           else
534             bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
535         }
536 
537         prop = bdf_get_font_property( font, "RESOLUTION_X" );
538         if ( prop )
539           value = prop->value.l;
540         else
541           value = (long)font->resolution_x;
542         if ( value )
543         {
544 #ifdef FT_DEBUG_LEVEL_TRACE
545           if ( value < 0 )
546             FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" ));
547 #endif
548           if ( value > 0x7FFF || value < -0x7FFF )
549           {
550             resolution_x = 0x7FFF;
551             FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n",
552                         resolution_x ));
553           }
554           else
555             resolution_x = FT_ABS( (FT_Short)value );
556         }
557 
558         prop = bdf_get_font_property( font, "RESOLUTION_Y" );
559         if ( prop )
560           value = prop->value.l;
561         else
562           value = (long)font->resolution_y;
563         if ( value )
564         {
565 #ifdef FT_DEBUG_LEVEL_TRACE
566           if ( value < 0 )
567             FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" ));
568 #endif
569           if ( value > 0x7FFF || value < -0x7FFF )
570           {
571             resolution_y = 0x7FFF;
572             FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n",
573                         resolution_y ));
574           }
575           else
576             resolution_y = FT_ABS( (FT_Short)value );
577         }
578 
579         if ( bsize->y_ppem == 0 )
580         {
581           bsize->y_ppem = bsize->size;
582           if ( resolution_y )
583             bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
584         }
585         if ( resolution_x && resolution_y )
586           bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
587                                      resolution_x,
588                                      resolution_y );
589         else
590           bsize->x_ppem = bsize->y_ppem;
591       }
592 
593       /* encoding table */
594       {
595         bdf_glyph_t*   cur = font->glyphs;
596         unsigned long  n;
597 
598 
599         if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
600           goto Exit;
601 
602         face->default_glyph = 0;
603         for ( n = 0; n < font->glyphs_size; n++ )
604         {
605           (face->en_table[n]).enc = cur[n].encoding;
606           FT_TRACE4(( "  idx %d, val 0x%lX\n", n, cur[n].encoding ));
607           (face->en_table[n]).glyph = (FT_UShort)n;
608 
609           if ( cur[n].encoding == font->default_char )
610           {
611             if ( n < FT_UINT_MAX )
612               face->default_glyph = (FT_UInt)n;
613             else
614               FT_TRACE1(( "BDF_Face_Init:"
615                           " idx %d is too large for this system\n", n ));
616           }
617         }
618       }
619 
620       /* charmaps */
621       {
622         bdf_property_t  *charset_registry, *charset_encoding;
623         FT_Bool          unicode_charmap  = 0;
624 
625 
626         charset_registry =
627           bdf_get_font_property( font, "CHARSET_REGISTRY" );
628         charset_encoding =
629           bdf_get_font_property( font, "CHARSET_ENCODING" );
630         if ( charset_registry && charset_encoding )
631         {
632           if ( charset_registry->format == BDF_ATOM &&
633                charset_encoding->format == BDF_ATOM &&
634                charset_registry->value.atom         &&
635                charset_encoding->value.atom         )
636           {
637             const char*  s;
638 
639 
640             if ( FT_STRDUP( face->charset_encoding,
641                             charset_encoding->value.atom ) ||
642                  FT_STRDUP( face->charset_registry,
643                             charset_registry->value.atom ) )
644               goto Exit;
645 
646             /* Uh, oh, compare first letters manually to avoid dependency */
647             /* on locales.                                                */
648             s = face->charset_registry;
649             if ( ( s[0] == 'i' || s[0] == 'I' ) &&
650                  ( s[1] == 's' || s[1] == 'S' ) &&
651                  ( s[2] == 'o' || s[2] == 'O' ) )
652             {
653               s += 3;
654               if ( !ft_strcmp( s, "10646" )                      ||
655                    ( !ft_strcmp( s, "8859" ) &&
656                      !ft_strcmp( face->charset_encoding, "1" ) ) )
657                 unicode_charmap = 1;
658               /* another name for ASCII */
659               else if ( !ft_strcmp( s, "646.1991" )                 &&
660                         !ft_strcmp( face->charset_encoding, "IRV" ) )
661                 unicode_charmap = 1;
662             }
663 
664             {
665               FT_CharMapRec  charmap;
666 
667 
668               charmap.face        = FT_FACE( face );
669               charmap.encoding    = FT_ENCODING_NONE;
670               /* initial platform/encoding should indicate unset status? */
671               charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
672               charmap.encoding_id = TT_APPLE_ID_DEFAULT;
673 
674               if ( unicode_charmap )
675               {
676                 charmap.encoding    = FT_ENCODING_UNICODE;
677                 charmap.platform_id = TT_PLATFORM_MICROSOFT;
678                 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
679               }
680 
681               error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
682             }
683 
684             goto Exit;
685           }
686         }
687 
688         /* otherwise assume Adobe standard encoding */
689 
690         {
691           FT_CharMapRec  charmap;
692 
693 
694           charmap.face        = FT_FACE( face );
695           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
696           charmap.platform_id = TT_PLATFORM_ADOBE;
697           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
698 
699           error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
700 
701           /* Select default charmap */
702           if ( bdfface->num_charmaps )
703             bdfface->charmap = bdfface->charmaps[0];
704         }
705       }
706     }
707 
708   Exit:
709     return error;
710 
711   Fail:
712     BDF_Face_Done( bdfface );
713     return FT_THROW( Unknown_File_Format );
714   }
715 
716 
717   FT_CALLBACK_DEF( FT_Error )
BDF_Size_Select(FT_Size size,FT_ULong strike_index)718   BDF_Size_Select( FT_Size   size,
719                    FT_ULong  strike_index )
720   {
721     bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
722 
723 
724     FT_Select_Metrics( size->face, strike_index );
725 
726     size->metrics.ascender    = bdffont->font_ascent * 64;
727     size->metrics.descender   = -bdffont->font_descent * 64;
728     size->metrics.max_advance = bdffont->bbx.width * 64;
729 
730     return FT_Err_Ok;
731   }
732 
733 
734   FT_CALLBACK_DEF( FT_Error )
BDF_Size_Request(FT_Size size,FT_Size_Request req)735   BDF_Size_Request( FT_Size          size,
736                     FT_Size_Request  req )
737   {
738     FT_Face          face    = size->face;
739     FT_Bitmap_Size*  bsize   = face->available_sizes;
740     bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
741     FT_Error         error   = FT_ERR( Invalid_Pixel_Size );
742     FT_Long          height;
743 
744 
745     height = FT_REQUEST_HEIGHT( req );
746     height = ( height + 32 ) >> 6;
747 
748     switch ( req->type )
749     {
750     case FT_SIZE_REQUEST_TYPE_NOMINAL:
751       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
752         error = FT_Err_Ok;
753       break;
754 
755     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
756       if ( height == ( bdffont->font_ascent +
757                        bdffont->font_descent ) )
758         error = FT_Err_Ok;
759       break;
760 
761     default:
762       error = FT_THROW( Unimplemented_Feature );
763       break;
764     }
765 
766     if ( error )
767       return error;
768     else
769       return BDF_Size_Select( size, 0 );
770   }
771 
772 
773 
774   FT_CALLBACK_DEF( FT_Error )
BDF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)775   BDF_Glyph_Load( FT_GlyphSlot  slot,
776                   FT_Size       size,
777                   FT_UInt       glyph_index,
778                   FT_Int32      load_flags )
779   {
780     BDF_Face     bdf    = (BDF_Face)FT_SIZE_FACE( size );
781     FT_Face      face   = FT_FACE( bdf );
782     FT_Error     error  = FT_Err_Ok;
783     FT_Bitmap*   bitmap = &slot->bitmap;
784     bdf_glyph_t  glyph;
785     int          bpp    = bdf->bdffont->bpp;
786 
787     FT_UNUSED( load_flags );
788 
789 
790     if ( !face )
791     {
792       error = FT_THROW( Invalid_Face_Handle );
793       goto Exit;
794     }
795 
796     if ( glyph_index >= (FT_UInt)face->num_glyphs )
797     {
798       error = FT_THROW( Invalid_Argument );
799       goto Exit;
800     }
801 
802     FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
803 
804     /* index 0 is the undefined glyph */
805     if ( glyph_index == 0 )
806       glyph_index = bdf->default_glyph;
807     else
808       glyph_index--;
809 
810     /* slot, bitmap => freetype, glyph => bdflib */
811     glyph = bdf->bdffont->glyphs[glyph_index];
812 
813     bitmap->rows  = glyph.bbx.height;
814     bitmap->width = glyph.bbx.width;
815     if ( glyph.bpr > FT_INT_MAX )
816       FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
817                    glyph.bpr ));
818     bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
819 
820     /* note: we don't allocate a new array to hold the bitmap; */
821     /*       we can simply point to it                         */
822     ft_glyphslot_set_bitmap( slot, glyph.bitmap );
823 
824     switch ( bpp )
825     {
826     case 1:
827       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
828       break;
829     case 2:
830       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
831       break;
832     case 4:
833       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
834       break;
835     case 8:
836       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
837       bitmap->num_grays  = 256;
838       break;
839     }
840 
841     slot->format      = FT_GLYPH_FORMAT_BITMAP;
842     slot->bitmap_left = glyph.bbx.x_offset;
843     slot->bitmap_top  = glyph.bbx.ascent;
844 
845     slot->metrics.horiAdvance  = (FT_Pos)( glyph.dwidth * 64 );
846     slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 );
847     slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 );
848     slot->metrics.width        = (FT_Pos)( bitmap->width * 64 );
849     slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
850 
851     /*
852      * XXX DWIDTH1 and VVECTOR should be parsed and
853      * used here, provided such fonts do exist.
854      */
855     ft_synthesize_vertical_metrics( &slot->metrics,
856                                     bdf->bdffont->bbx.height * 64 );
857 
858   Exit:
859     return error;
860   }
861 
862 
863  /*
864   *
865   * BDF SERVICE
866   *
867   */
868 
869   static FT_Error
bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)870   bdf_get_bdf_property( BDF_Face          face,
871                         const char*       prop_name,
872                         BDF_PropertyRec  *aproperty )
873   {
874     bdf_property_t*  prop;
875 
876 
877     FT_ASSERT( face && face->bdffont );
878 
879     prop = bdf_get_font_property( face->bdffont, prop_name );
880     if ( prop )
881     {
882       switch ( prop->format )
883       {
884       case BDF_ATOM:
885         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
886         aproperty->u.atom = prop->value.atom;
887         break;
888 
889       case BDF_INTEGER:
890         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
891         {
892           FT_TRACE1(( "bdf_get_bdf_property:"
893                       " too large integer 0x%x is truncated\n" ));
894         }
895         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
896         aproperty->u.integer = (FT_Int32)prop->value.l;
897         break;
898 
899       case BDF_CARDINAL:
900         if ( prop->value.ul > 0xFFFFFFFFUL )
901         {
902           FT_TRACE1(( "bdf_get_bdf_property:"
903                       " too large cardinal 0x%x is truncated\n" ));
904         }
905         aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
906         aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
907         break;
908 
909       default:
910         goto Fail;
911       }
912       return 0;
913     }
914 
915   Fail:
916     return FT_THROW( Invalid_Argument );
917   }
918 
919 
920   static FT_Error
bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)921   bdf_get_charset_id( BDF_Face      face,
922                       const char*  *acharset_encoding,
923                       const char*  *acharset_registry )
924   {
925     *acharset_encoding = face->charset_encoding;
926     *acharset_registry = face->charset_registry;
927 
928     return 0;
929   }
930 
931 
932   static const FT_Service_BDFRec  bdf_service_bdf =
933   {
934     (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,       /* get_charset_id */
935     (FT_BDF_GetPropertyFunc) bdf_get_bdf_property      /* get_property   */
936   };
937 
938 
939  /*
940   *
941   * SERVICES LIST
942   *
943   */
944 
945   static const FT_ServiceDescRec  bdf_services[] =
946   {
947     { FT_SERVICE_ID_BDF,         &bdf_service_bdf },
948     { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF },
949     { NULL, NULL }
950   };
951 
952 
953   FT_CALLBACK_DEF( FT_Module_Interface )
bdf_driver_requester(FT_Module module,const char * name)954   bdf_driver_requester( FT_Module    module,
955                         const char*  name )
956   {
957     FT_UNUSED( module );
958 
959     return ft_service_list_lookup( bdf_services, name );
960   }
961 
962 
963 
964   FT_CALLBACK_TABLE_DEF
965   const FT_Driver_ClassRec  bdf_driver_class =
966   {
967     {
968       FT_MODULE_FONT_DRIVER         |
969       FT_MODULE_DRIVER_NO_OUTLINES,
970       sizeof ( FT_DriverRec ),
971 
972       "bdf",
973       0x10000L,
974       0x20000L,
975 
976       NULL,    /* module-specific interface */
977 
978       NULL,                     /* FT_Module_Constructor  module_init   */
979       NULL,                     /* FT_Module_Destructor   module_done   */
980       bdf_driver_requester      /* FT_Module_Requester    get_interface */
981     },
982 
983     sizeof ( BDF_FaceRec ),
984     sizeof ( FT_SizeRec ),
985     sizeof ( FT_GlyphSlotRec ),
986 
987     BDF_Face_Init,              /* FT_Face_InitFunc  init_face */
988     BDF_Face_Done,              /* FT_Face_DoneFunc  done_face */
989     NULL,                       /* FT_Size_InitFunc  init_size */
990     NULL,                       /* FT_Size_DoneFunc  done_size */
991     NULL,                       /* FT_Slot_InitFunc  init_slot */
992     NULL,                       /* FT_Slot_DoneFunc  done_slot */
993 
994     BDF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
995 
996     NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
997     NULL,                       /* FT_Face_AttachFunc       attach_file  */
998     NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
999 
1000     BDF_Size_Request,           /* FT_Size_RequestFunc  request_size */
1001     BDF_Size_Select             /* FT_Size_SelectFunc   select_size  */
1002   };
1003 
1004 
1005 /* END */
1006