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