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