• 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 
28 #include <freetype/internal/ftdebug.h>
29 #include <freetype/internal/ftstream.h>
30 #include <freetype/internal/ftobjs.h>
31 #include <freetype/ftbdf.h>
32 #include <freetype/ttnameid.h>
33 
34 #include <freetype/internal/services/svbdf.h>
35 #include <freetype/internal/services/svfntfmt.h>
36 
37 #include "bdf.h"
38 #include "bdfdrivr.h"
39 
40 #include "bdferror.h"
41 
42 
43   /**************************************************************************
44    *
45    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
46    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
47    * messages during execution.
48    */
49 #undef  FT_COMPONENT
50 #define FT_COMPONENT  bdfdriver
51 
52 
53   typedef struct  BDF_CMapRec_
54   {
55     FT_CMapRec        cmap;
56     FT_ULong          num_encodings; /* ftobjs.h: FT_CMap->clazz->size */
57     BDF_encoding_el*  encodings;
58 
59   } BDF_CMapRec, *BDF_CMap;
60 
61 
62   FT_CALLBACK_DEF( FT_Error )
bdf_cmap_init(FT_CMap bdfcmap,FT_Pointer init_data)63   bdf_cmap_init( FT_CMap     bdfcmap,
64                  FT_Pointer  init_data )
65   {
66     BDF_CMap  cmap = (BDF_CMap)bdfcmap;
67     BDF_Face  face = (BDF_Face)FT_CMAP_FACE( cmap );
68     FT_UNUSED( init_data );
69 
70 
71     cmap->num_encodings = face->bdffont->glyphs_used;
72     cmap->encodings     = face->en_table;
73 
74     return FT_Err_Ok;
75   }
76 
77 
78   FT_CALLBACK_DEF( void )
bdf_cmap_done(FT_CMap bdfcmap)79   bdf_cmap_done( FT_CMap  bdfcmap )
80   {
81     BDF_CMap  cmap = (BDF_CMap)bdfcmap;
82 
83 
84     cmap->encodings     = NULL;
85     cmap->num_encodings = 0;
86   }
87 
88 
89   FT_CALLBACK_DEF( FT_UInt )
bdf_cmap_char_index(FT_CMap bdfcmap,FT_UInt32 charcode)90   bdf_cmap_char_index( FT_CMap    bdfcmap,
91                        FT_UInt32  charcode )
92   {
93     BDF_CMap          cmap      = (BDF_CMap)bdfcmap;
94     BDF_encoding_el*  encodings = cmap->encodings;
95     FT_UShort         result    = 0; /* encodings->glyph */
96 
97     FT_ULong  min = 0;
98     FT_ULong  max = cmap->num_encodings;
99     FT_ULong  mid = ( min + max ) >> 1;
100 
101 
102     while ( min < max )
103     {
104       FT_ULong  code = encodings[mid].enc;
105 
106 
107       if ( charcode == code )
108       {
109         /* increase glyph index by 1 --              */
110         /* we reserve slot 0 for the undefined glyph */
111         result = encodings[mid].glyph + 1;
112         break;
113       }
114 
115       if ( charcode < code )
116         max = mid;
117       else
118         min = mid + 1;
119 
120       /* reasonable prediction in a continuous block */
121       mid += charcode - code;
122       if ( mid >= max || mid < min )
123         mid = ( min + max ) >> 1;
124     }
125 
126     return result;
127   }
128 
129 
130   FT_CALLBACK_DEF( FT_UInt )
bdf_cmap_char_next(FT_CMap bdfcmap,FT_UInt32 * acharcode)131   bdf_cmap_char_next( FT_CMap     bdfcmap,
132                       FT_UInt32  *acharcode )
133   {
134     BDF_CMap          cmap      = (BDF_CMap)bdfcmap;
135     BDF_encoding_el*  encodings = cmap->encodings;
136     FT_UShort         result   = 0;  /* encodings->glyph */
137     FT_ULong          charcode = *acharcode + 1;
138 
139     FT_ULong  min = 0;
140     FT_ULong  max = cmap->num_encodings;
141     FT_ULong  mid = ( min + max ) >> 1;
142 
143 
144     while ( min < max )
145     {
146       FT_ULong  code = encodings[mid].enc;
147 
148 
149       if ( charcode == code )
150       {
151         /* increase glyph index by 1 --              */
152         /* we reserve slot 0 for the undefined glyph */
153         result = encodings[mid].glyph + 1;
154         goto Exit;
155       }
156 
157       if ( charcode < code )
158         max = mid;
159       else
160         min = mid + 1;
161 
162       /* prediction in a continuous block */
163       mid += charcode - code;
164       if ( mid >= max || mid < min )
165         mid = ( min + max ) >> 1;
166     }
167 
168     charcode = 0;
169     if ( min < cmap->num_encodings )
170     {
171       charcode = encodings[min].enc;
172       result   = encodings[min].glyph + 1;
173     }
174 
175   Exit:
176     if ( charcode > 0xFFFFFFFFUL )
177     {
178       FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%lx > 32bit API",
179                   charcode ));
180       *acharcode = 0;
181       /* XXX: result should be changed to indicate an overflow error */
182     }
183     else
184       *acharcode = (FT_UInt32)charcode;
185     return result;
186   }
187 
188 
189   static
190   const FT_CMap_ClassRec  bdf_cmap_class =
191   {
192     sizeof ( BDF_CMapRec ),
193     bdf_cmap_init,
194     bdf_cmap_done,
195     bdf_cmap_char_index,
196     bdf_cmap_char_next,
197 
198     NULL, NULL, NULL, NULL, NULL
199   };
200 
201 
202   static FT_Error
bdf_interpret_style(BDF_Face bdf)203   bdf_interpret_style( BDF_Face  bdf )
204   {
205     FT_Error         error  = FT_Err_Ok;
206     FT_Face          face   = FT_FACE( bdf );
207     FT_Memory        memory = face->memory;
208     bdf_font_t*      font   = bdf->bdffont;
209     bdf_property_t*  prop;
210 
211     const char*   strings[4] = { NULL, NULL, NULL, NULL };
212     size_t        lengths[4], nn, len;
213 
214 
215     face->style_flags = 0;
216 
217     prop = bdf_get_font_property( font, "SLANT" );
218     if ( prop && prop->format == BDF_ATOM                             &&
219          prop->value.atom                                             &&
220          ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
221            *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
222     {
223       face->style_flags |= FT_STYLE_FLAG_ITALIC;
224       strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
225                    ? "Oblique"
226                    : "Italic";
227     }
228 
229     prop = bdf_get_font_property( font, "WEIGHT_NAME" );
230     if ( prop && prop->format == BDF_ATOM                             &&
231          prop->value.atom                                             &&
232          ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
233     {
234       face->style_flags |= FT_STYLE_FLAG_BOLD;
235       strings[1] = "Bold";
236     }
237 
238     prop = bdf_get_font_property( font, "SETWIDTH_NAME" );
239     if ( prop && prop->format == BDF_ATOM                              &&
240          prop->value.atom && *(prop->value.atom)                       &&
241          !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
242       strings[3] = (const char *)(prop->value.atom);
243 
244     prop = bdf_get_font_property( font, "ADD_STYLE_NAME" );
245     if ( prop && prop->format == BDF_ATOM                              &&
246          prop->value.atom && *(prop->value.atom)                       &&
247          !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
248       strings[0] = (const char *)(prop->value.atom);
249 
250     for ( len = 0, nn = 0; nn < 4; nn++ )
251     {
252       lengths[nn] = 0;
253       if ( strings[nn] )
254       {
255         lengths[nn] = ft_strlen( strings[nn] );
256         len        += lengths[nn] + 1;
257       }
258     }
259 
260     if ( len == 0 )
261     {
262       strings[0] = "Regular";
263       lengths[0] = ft_strlen( strings[0] );
264       len        = lengths[0] + 1;
265     }
266 
267     {
268       char*  s;
269 
270 
271       if ( FT_QALLOC( face->style_name, len ) )
272         return error;
273 
274       s = face->style_name;
275 
276       for ( nn = 0; nn < 4; nn++ )
277       {
278         const char*  src = strings[nn];
279 
280 
281         len = lengths[nn];
282 
283         if ( !src )
284           continue;
285 
286         /* separate elements with a space */
287         if ( s != face->style_name )
288           *s++ = ' ';
289 
290         ft_memcpy( s, src, len );
291 
292         /* need to convert spaces to dashes for */
293         /* add_style_name and setwidth_name     */
294         if ( nn == 0 || nn == 3 )
295         {
296           size_t  mm;
297 
298 
299           for ( mm = 0; mm < len; mm++ )
300             if ( s[mm] == ' ' )
301               s[mm] = '-';
302         }
303 
304         s += len;
305       }
306       *s = 0;
307     }
308 
309     return error;
310   }
311 
312 
313   FT_CALLBACK_DEF( void )
BDF_Face_Done(FT_Face bdfface)314   BDF_Face_Done( FT_Face  bdfface )         /* BDF_Face */
315   {
316     BDF_Face   face = (BDF_Face)bdfface;
317     FT_Memory  memory;
318 
319 
320     if ( !face )
321       return;
322 
323     memory = FT_FACE_MEMORY( face );
324 
325     bdf_free_font( face->bdffont );
326 
327     FT_FREE( face->en_table );
328 
329     FT_FREE( face->charset_encoding );
330     FT_FREE( face->charset_registry );
331     FT_FREE( bdfface->family_name );
332     FT_FREE( bdfface->style_name );
333 
334     FT_FREE( bdfface->available_sizes );
335 
336     FT_FREE( face->bdffont );
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  = FT_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 
357 
358     FT_TRACE2(( "BDF driver\n" ));
359 
360     if ( FT_STREAM_SEEK( 0 ) )
361       goto Exit;
362 
363     options.correct_metrics = 1;   /* FZ XXX: options semantics */
364     options.keep_unencoded  = 1;
365     options.keep_comments   = 0;
366     options.font_spacing    = BDF_PROPORTIONAL;
367 
368     error = bdf_load_font( stream, memory, &options, &font );
369     if ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
370     {
371       FT_TRACE2(( "  not a BDF file\n" ));
372       goto Fail;
373     }
374     else if ( error )
375       goto Exit;
376 
377     /* we have a bdf font: let's construct the face object */
378     face->bdffont = font;
379 
380     /* BDF cannot have multiple faces in a single font file.
381      * XXX: non-zero face_index is already invalid argument, but
382      *      Type1, Type42 driver has a convention to return
383      *      an invalid argument error when the font could be
384      *      opened by the specified driver.
385      */
386     if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
387     {
388       FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
389       BDF_Face_Done( bdfface );
390       return FT_THROW( Invalid_Argument );
391     }
392 
393     {
394       bdf_property_t*  prop = NULL;
395 
396 
397       FT_TRACE4(( "  number of glyphs: allocated %ld (used %ld)\n",
398                   font->glyphs_size,
399                   font->glyphs_used ));
400       FT_TRACE4(( "  number of unencoded glyphs: allocated %ld (used %ld)\n",
401                   font->unencoded_size,
402                   font->unencoded_used ));
403 
404       bdfface->num_faces  = 1;
405       bdfface->face_index = 0;
406 
407       bdfface->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
408                              FT_FACE_FLAG_HORIZONTAL;
409 
410       prop = bdf_get_font_property( font, "SPACING" );
411       if ( prop && prop->format == BDF_ATOM                             &&
412            prop->value.atom                                             &&
413            ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
414              *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
415         bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
416 
417       /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL   */
418       /* FZ XXX: I need a font to implement this */
419 
420       prop = bdf_get_font_property( font, "FAMILY_NAME" );
421       if ( prop && prop->value.atom )
422       {
423         if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
424           goto Exit;
425       }
426       else
427         bdfface->family_name = NULL;
428 
429       if ( FT_SET_ERROR( bdf_interpret_style( face ) ) )
430         goto Exit;
431 
432       /* the number of glyphs (with one slot for the undefined glyph */
433       /* at position 0 and all unencoded glyphs)                     */
434       bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 );
435 
436       bdfface->num_fixed_sizes = 1;
437       if ( FT_NEW( bdfface->available_sizes ) )
438         goto Exit;
439 
440       {
441         FT_Bitmap_Size*  bsize = bdfface->available_sizes;
442         FT_Short         resolution_x = 0, resolution_y = 0;
443         long             value;
444 
445 
446         /* sanity checks */
447         if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF )
448         {
449           font->font_ascent = font->font_ascent < 0 ? -0x7FFF : 0x7FFF;
450           FT_TRACE0(( "BDF_Face_Init: clamping font ascent to value %ld\n",
451                       font->font_ascent ));
452         }
453         if ( font->font_descent > 0x7FFF || font->font_descent < -0x7FFF )
454         {
455           font->font_descent = font->font_descent < 0 ? -0x7FFF : 0x7FFF;
456           FT_TRACE0(( "BDF_Face_Init: clamping font descent to value %ld\n",
457                       font->font_descent ));
458         }
459 
460         bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
461 
462         prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
463         if ( prop )
464         {
465 #ifdef FT_DEBUG_LEVEL_TRACE
466           if ( prop->value.l < 0 )
467             FT_TRACE0(( "BDF_Face_Init: negative average width\n" ));
468 #endif
469           if ( prop->value.l >    0x7FFFL * 10 - 5   ||
470                prop->value.l < -( 0x7FFFL * 10 - 5 ) )
471           {
472             bsize->width = 0x7FFF;
473             FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n",
474                         bsize->width ));
475           }
476           else
477             bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
478         }
479         else
480         {
481           /* this is a heuristical value */
482           bsize->width = ( bsize->height * 2 + 1 ) / 3;
483         }
484 
485         prop = bdf_get_font_property( font, "POINT_SIZE" );
486         if ( prop )
487         {
488 #ifdef FT_DEBUG_LEVEL_TRACE
489           if ( prop->value.l < 0 )
490             FT_TRACE0(( "BDF_Face_Init: negative point size\n" ));
491 #endif
492           /* convert from 722.7 decipoints to 72 points per inch */
493           if ( prop->value.l >  0x504C2L || /* 0x7FFF * 72270/7200 */
494                prop->value.l < -0x504C2L )
495           {
496             bsize->size = 0x7FFF;
497             FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
498                         bsize->size ));
499           }
500           else
501             bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
502                                      64 * 7200,
503                                      72270L );
504         }
505         else if ( font->point_size )
506         {
507           if ( font->point_size > 0x7FFF )
508           {
509             bsize->size = 0x7FFF;
510             FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
511                         bsize->size ));
512           }
513           else
514             bsize->size = (FT_Pos)font->point_size << 6;
515         }
516         else
517         {
518           /* this is a heuristical value */
519           bsize->size = bsize->width * 64;
520         }
521 
522         prop = bdf_get_font_property( font, "PIXEL_SIZE" );
523         if ( prop )
524         {
525 #ifdef FT_DEBUG_LEVEL_TRACE
526           if ( prop->value.l < 0 )
527             FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" ));
528 #endif
529           if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF )
530           {
531             bsize->y_ppem = 0x7FFF << 6;
532             FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %ld\n",
533                         bsize->y_ppem ));
534           }
535           else
536             bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
537         }
538 
539         prop = bdf_get_font_property( font, "RESOLUTION_X" );
540         if ( prop )
541           value = prop->value.l;
542         else
543           value = (long)font->resolution_x;
544         if ( value )
545         {
546 #ifdef FT_DEBUG_LEVEL_TRACE
547           if ( value < 0 )
548             FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" ));
549 #endif
550           if ( value > 0x7FFF || value < -0x7FFF )
551           {
552             resolution_x = 0x7FFF;
553             FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n",
554                         resolution_x ));
555           }
556           else
557             resolution_x = FT_ABS( (FT_Short)value );
558         }
559 
560         prop = bdf_get_font_property( font, "RESOLUTION_Y" );
561         if ( prop )
562           value = prop->value.l;
563         else
564           value = (long)font->resolution_y;
565         if ( value )
566         {
567 #ifdef FT_DEBUG_LEVEL_TRACE
568           if ( value < 0 )
569             FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" ));
570 #endif
571           if ( value > 0x7FFF || value < -0x7FFF )
572           {
573             resolution_y = 0x7FFF;
574             FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n",
575                         resolution_y ));
576           }
577           else
578             resolution_y = FT_ABS( (FT_Short)value );
579         }
580 
581         if ( bsize->y_ppem == 0 )
582         {
583           bsize->y_ppem = bsize->size;
584           if ( resolution_y )
585             bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
586         }
587         if ( resolution_x && resolution_y )
588           bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
589                                      resolution_x,
590                                      resolution_y );
591         else
592           bsize->x_ppem = bsize->y_ppem;
593       }
594 
595       /* encoding table */
596       {
597         bdf_glyph_t*   cur = font->glyphs;
598         unsigned long  n;
599 
600 
601         if ( FT_QNEW_ARRAY( face->en_table, font->glyphs_size ) )
602           goto Exit;
603 
604         face->default_glyph = 0;
605         for ( n = 0; n < font->glyphs_size; n++ )
606         {
607           (face->en_table[n]).enc = cur[n].encoding;
608           FT_TRACE4(( "  idx %ld, val 0x%lX\n", n, cur[n].encoding ));
609           (face->en_table[n]).glyph = (FT_UShort)n;
610 
611           if ( cur[n].encoding == font->default_char )
612           {
613             if ( n < FT_UINT_MAX )
614               face->default_glyph = (FT_UInt)n;
615             else
616               FT_TRACE1(( "BDF_Face_Init:"
617                           " idx %ld is too large for this system\n", n ));
618           }
619         }
620       }
621 
622       /* charmaps */
623       {
624         bdf_property_t  *charset_registry, *charset_encoding;
625         FT_Bool          unicode_charmap  = 0;
626 
627 
628         charset_registry =
629           bdf_get_font_property( font, "CHARSET_REGISTRY" );
630         charset_encoding =
631           bdf_get_font_property( font, "CHARSET_ENCODING" );
632         if ( charset_registry && charset_encoding )
633         {
634           if ( charset_registry->format == BDF_ATOM &&
635                charset_encoding->format == BDF_ATOM &&
636                charset_registry->value.atom         &&
637                charset_encoding->value.atom         )
638           {
639             const char*  s;
640 
641 
642             if ( FT_STRDUP( face->charset_encoding,
643                             charset_encoding->value.atom ) ||
644                  FT_STRDUP( face->charset_registry,
645                             charset_registry->value.atom ) )
646               goto Exit;
647 
648             /* Uh, oh, compare first letters manually to avoid dependency */
649             /* on locales.                                                */
650             s = face->charset_registry;
651             if ( ( s[0] == 'i' || s[0] == 'I' ) &&
652                  ( s[1] == 's' || s[1] == 'S' ) &&
653                  ( s[2] == 'o' || s[2] == 'O' ) )
654             {
655               s += 3;
656               if ( !ft_strcmp( s, "10646" )                      ||
657                    ( !ft_strcmp( s, "8859" ) &&
658                      !ft_strcmp( face->charset_encoding, "1" ) ) )
659                 unicode_charmap = 1;
660               /* another name for ASCII */
661               else if ( !ft_strcmp( s, "646.1991" )                 &&
662                         !ft_strcmp( face->charset_encoding, "IRV" ) )
663                 unicode_charmap = 1;
664             }
665 
666             {
667               FT_CharMapRec  charmap;
668 
669 
670               charmap.face        = FT_FACE( face );
671               charmap.encoding    = FT_ENCODING_NONE;
672               /* initial platform/encoding should indicate unset status? */
673               charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
674               charmap.encoding_id = TT_APPLE_ID_DEFAULT;
675 
676               if ( unicode_charmap )
677               {
678                 charmap.encoding    = FT_ENCODING_UNICODE;
679                 charmap.platform_id = TT_PLATFORM_MICROSOFT;
680                 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
681               }
682 
683               error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
684             }
685 
686             goto Exit;
687           }
688         }
689 
690         /* otherwise assume Adobe standard encoding */
691 
692         {
693           FT_CharMapRec  charmap;
694 
695 
696           charmap.face        = FT_FACE( face );
697           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
698           charmap.platform_id = TT_PLATFORM_ADOBE;
699           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
700 
701           error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
702 
703           /* Select default charmap */
704           if ( bdfface->num_charmaps )
705             bdfface->charmap = bdfface->charmaps[0];
706         }
707       }
708     }
709 
710   Exit:
711     return error;
712 
713   Fail:
714     BDF_Face_Done( bdfface );
715     return FT_THROW( Unknown_File_Format );
716   }
717 
718 
719   FT_CALLBACK_DEF( FT_Error )
BDF_Size_Select(FT_Size size,FT_ULong strike_index)720   BDF_Size_Select( FT_Size   size,
721                    FT_ULong  strike_index )
722   {
723     bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
724 
725 
726     FT_Select_Metrics( size->face, strike_index );
727 
728     size->metrics.ascender    = bdffont->font_ascent * 64;
729     size->metrics.descender   = -bdffont->font_descent * 64;
730     size->metrics.max_advance = bdffont->bbx.width * 64;
731 
732     return FT_Err_Ok;
733   }
734 
735 
736   FT_CALLBACK_DEF( FT_Error )
BDF_Size_Request(FT_Size size,FT_Size_Request req)737   BDF_Size_Request( FT_Size          size,
738                     FT_Size_Request  req )
739   {
740     FT_Face          face    = size->face;
741     FT_Bitmap_Size*  bsize   = face->available_sizes;
742     bdf_font_t*      bdffont = ( (BDF_Face)face )->bdffont;
743     FT_Error         error   = FT_ERR( Invalid_Pixel_Size );
744     FT_Long          height;
745 
746 
747     height = FT_REQUEST_HEIGHT( req );
748     height = ( height + 32 ) >> 6;
749 
750     switch ( req->type )
751     {
752     case FT_SIZE_REQUEST_TYPE_NOMINAL:
753       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
754         error = FT_Err_Ok;
755       break;
756 
757     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
758       if ( height == ( bdffont->font_ascent +
759                        bdffont->font_descent ) )
760         error = FT_Err_Ok;
761       break;
762 
763     default:
764       error = FT_THROW( Unimplemented_Feature );
765       break;
766     }
767 
768     if ( error )
769       return error;
770     else
771       return BDF_Size_Select( size, 0 );
772   }
773 
774 
775 
776   FT_CALLBACK_DEF( FT_Error )
BDF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)777   BDF_Glyph_Load( FT_GlyphSlot  slot,
778                   FT_Size       size,
779                   FT_UInt       glyph_index,
780                   FT_Int32      load_flags )
781   {
782     BDF_Face     bdf    = (BDF_Face)FT_SIZE_FACE( size );
783     FT_Face      face   = FT_FACE( bdf );
784     FT_Error     error  = FT_Err_Ok;
785     FT_Bitmap*   bitmap = &slot->bitmap;
786     bdf_glyph_t  glyph;
787     int          bpp    = bdf->bdffont->bpp;
788 
789     FT_UNUSED( load_flags );
790 
791 
792     if ( !face )
793     {
794       error = FT_THROW( Invalid_Face_Handle );
795       goto Exit;
796     }
797 
798     if ( glyph_index >= (FT_UInt)face->num_glyphs )
799     {
800       error = FT_THROW( Invalid_Argument );
801       goto Exit;
802     }
803 
804     FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
805 
806     /* index 0 is the undefined glyph */
807     if ( glyph_index == 0 )
808       glyph_index = bdf->default_glyph;
809     else
810       glyph_index--;
811 
812     /* slot, bitmap => freetype, glyph => bdflib */
813     glyph = bdf->bdffont->glyphs[glyph_index];
814 
815     bitmap->rows  = glyph.bbx.height;
816     bitmap->width = glyph.bbx.width;
817     if ( glyph.bpr > FT_INT_MAX )
818       FT_TRACE1(( "BDF_Glyph_Load: too large pitch %ld is truncated\n",
819                    glyph.bpr ));
820     bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
821 
822     /* note: we don't allocate a new array to hold the bitmap; */
823     /*       we can simply point to it                         */
824     ft_glyphslot_set_bitmap( slot, glyph.bitmap );
825 
826     switch ( bpp )
827     {
828     case 1:
829       bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
830       break;
831     case 2:
832       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
833       break;
834     case 4:
835       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
836       break;
837     case 8:
838       bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
839       bitmap->num_grays  = 256;
840       break;
841     }
842 
843     slot->format      = FT_GLYPH_FORMAT_BITMAP;
844     slot->bitmap_left = glyph.bbx.x_offset;
845     slot->bitmap_top  = glyph.bbx.ascent;
846 
847     slot->metrics.horiAdvance  = (FT_Pos)( glyph.dwidth * 64 );
848     slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 );
849     slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 );
850     slot->metrics.width        = (FT_Pos)( bitmap->width * 64 );
851     slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
852 
853     /*
854      * XXX DWIDTH1 and VVECTOR should be parsed and
855      * used here, provided such fonts do exist.
856      */
857     ft_synthesize_vertical_metrics( &slot->metrics,
858                                     bdf->bdffont->bbx.height * 64 );
859 
860   Exit:
861     return error;
862   }
863 
864 
865  /*
866   *
867   * BDF SERVICE
868   *
869   */
870 
871   static FT_Error
bdf_get_bdf_property(BDF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)872   bdf_get_bdf_property( BDF_Face          face,
873                         const char*       prop_name,
874                         BDF_PropertyRec  *aproperty )
875   {
876     bdf_property_t*  prop;
877 
878 
879     FT_ASSERT( face && face->bdffont );
880 
881     prop = bdf_get_font_property( face->bdffont, prop_name );
882     if ( prop )
883     {
884       switch ( prop->format )
885       {
886       case BDF_ATOM:
887         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
888         aproperty->u.atom = prop->value.atom;
889         break;
890 
891       case BDF_INTEGER:
892         if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
893         {
894           FT_TRACE1(( "bdf_get_bdf_property:"
895                       " too large integer 0x%lx is truncated\n",
896                       prop->value.l ));
897         }
898         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
899         aproperty->u.integer = (FT_Int32)prop->value.l;
900         break;
901 
902       case BDF_CARDINAL:
903         if ( prop->value.ul > 0xFFFFFFFFUL )
904         {
905           FT_TRACE1(( "bdf_get_bdf_property:"
906                       " too large cardinal 0x%lx is truncated\n",
907                       prop->value.ul ));
908         }
909         aproperty->type       = BDF_PROPERTY_TYPE_CARDINAL;
910         aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
911         break;
912 
913       default:
914         goto Fail;
915       }
916       return 0;
917     }
918 
919   Fail:
920     return FT_THROW( Invalid_Argument );
921   }
922 
923 
924   static FT_Error
bdf_get_charset_id(BDF_Face face,const char ** acharset_encoding,const char ** acharset_registry)925   bdf_get_charset_id( BDF_Face      face,
926                       const char*  *acharset_encoding,
927                       const char*  *acharset_registry )
928   {
929     *acharset_encoding = face->charset_encoding;
930     *acharset_registry = face->charset_registry;
931 
932     return 0;
933   }
934 
935 
936   static const FT_Service_BDFRec  bdf_service_bdf =
937   {
938     (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,       /* get_charset_id */
939     (FT_BDF_GetPropertyFunc) bdf_get_bdf_property      /* get_property   */
940   };
941 
942 
943  /*
944   *
945   * SERVICES LIST
946   *
947   */
948 
949   static const FT_ServiceDescRec  bdf_services[] =
950   {
951     { FT_SERVICE_ID_BDF,         &bdf_service_bdf },
952     { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF },
953     { NULL, NULL }
954   };
955 
956 
957   FT_CALLBACK_DEF( FT_Module_Interface )
bdf_driver_requester(FT_Module module,const char * name)958   bdf_driver_requester( FT_Module    module,
959                         const char*  name )
960   {
961     FT_UNUSED( module );
962 
963     return ft_service_list_lookup( bdf_services, name );
964   }
965 
966 
967 
968   FT_CALLBACK_TABLE_DEF
969   const FT_Driver_ClassRec  bdf_driver_class =
970   {
971     {
972       FT_MODULE_FONT_DRIVER         |
973       FT_MODULE_DRIVER_NO_OUTLINES,
974       sizeof ( FT_DriverRec ),
975 
976       "bdf",
977       0x10000L,
978       0x20000L,
979 
980       NULL,    /* module-specific interface */
981 
982       NULL,                     /* FT_Module_Constructor  module_init   */
983       NULL,                     /* FT_Module_Destructor   module_done   */
984       bdf_driver_requester      /* FT_Module_Requester    get_interface */
985     },
986 
987     sizeof ( BDF_FaceRec ),
988     sizeof ( FT_SizeRec ),
989     sizeof ( FT_GlyphSlotRec ),
990 
991     BDF_Face_Init,              /* FT_Face_InitFunc  init_face */
992     BDF_Face_Done,              /* FT_Face_DoneFunc  done_face */
993     NULL,                       /* FT_Size_InitFunc  init_size */
994     NULL,                       /* FT_Size_DoneFunc  done_size */
995     NULL,                       /* FT_Slot_InitFunc  init_slot */
996     NULL,                       /* FT_Slot_DoneFunc  done_slot */
997 
998     BDF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
999 
1000     NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
1001     NULL,                       /* FT_Face_AttachFunc       attach_file  */
1002     NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
1003 
1004     BDF_Size_Request,           /* FT_Size_RequestFunc  request_size */
1005     BDF_Size_Select             /* FT_Size_SelectFunc   select_size  */
1006   };
1007 
1008 
1009 /* END */
1010