• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*  pcfdrivr.c
2 
3     FreeType font driver for pcf files
4 
5     Copyright (C) 2000-2004, 2006-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 <ft2build.h>
29 
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
33 #include FT_GZIP_H
34 #include FT_LZW_H
35 #include FT_BZIP2_H
36 #include FT_ERRORS_H
37 #include FT_BDF_H
38 #include FT_TRUETYPE_IDS_H
39 
40 #include "pcf.h"
41 #include "pcfdrivr.h"
42 #include "pcfread.h"
43 
44 #include "pcferror.h"
45 #include "pcfutil.h"
46 
47 #undef  FT_COMPONENT
48 #define FT_COMPONENT  trace_pcfread
49 
50 #include FT_SERVICE_BDF_H
51 #include FT_SERVICE_FONT_FORMAT_H
52 #include FT_SERVICE_PROPERTIES_H
53 #include FT_DRIVER_H
54 
55 
56   /**************************************************************************
57    *
58    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
59    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
60    * messages during execution.
61    */
62 #undef  FT_COMPONENT
63 #define FT_COMPONENT  trace_pcfdriver
64 
65 
66   /*
67    * This file uses X11 terminology for PCF data; an `encoding' in X11 speak
68    * is the same as a `character code' in FreeType speak.
69    */
70   typedef struct  PCF_CMapRec_
71   {
72     FT_CMapRec    root;
73     FT_ULong      num_encodings;
74     PCF_Encoding  encodings;
75 
76   } PCF_CMapRec, *PCF_CMap;
77 
78 
79   FT_CALLBACK_DEF( FT_Error )
pcf_cmap_init(FT_CMap pcfcmap,FT_Pointer init_data)80   pcf_cmap_init( FT_CMap     pcfcmap,   /* PCF_CMap */
81                  FT_Pointer  init_data )
82   {
83     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
84     PCF_Face  face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
85 
86     FT_UNUSED( init_data );
87 
88 
89     cmap->num_encodings = face->nencodings;
90     cmap->encodings     = face->encodings;
91 
92     return FT_Err_Ok;
93   }
94 
95 
96   FT_CALLBACK_DEF( void )
pcf_cmap_done(FT_CMap pcfcmap)97   pcf_cmap_done( FT_CMap  pcfcmap )         /* PCF_CMap */
98   {
99     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
100 
101 
102     cmap->encodings     = NULL;
103     cmap->num_encodings = 0;
104   }
105 
106 
107   FT_CALLBACK_DEF( FT_UInt )
pcf_cmap_char_index(FT_CMap pcfcmap,FT_UInt32 charcode)108   pcf_cmap_char_index( FT_CMap    pcfcmap,  /* PCF_CMap */
109                        FT_UInt32  charcode )
110   {
111     PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
112     PCF_Encoding  encodings = cmap->encodings;
113     FT_ULong      min, max, mid;
114     FT_UInt       result    = 0;
115 
116 
117     min = 0;
118     max = cmap->num_encodings;
119 
120     while ( min < max )
121     {
122       FT_ULong  code;
123 
124 
125       mid  = ( min + max ) >> 1;
126       code = encodings[mid].enc;
127 
128       if ( charcode == code )
129       {
130         result = encodings[mid].glyph;
131         break;
132       }
133 
134       if ( charcode < code )
135         max = mid;
136       else
137         min = mid + 1;
138     }
139 
140     return result;
141   }
142 
143 
144   FT_CALLBACK_DEF( FT_UInt )
pcf_cmap_char_next(FT_CMap pcfcmap,FT_UInt32 * acharcode)145   pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
146                       FT_UInt32  *acharcode )
147   {
148     PCF_CMap      cmap      = (PCF_CMap)pcfcmap;
149     PCF_Encoding  encodings = cmap->encodings;
150     FT_ULong      min, max, mid;
151     FT_ULong      charcode  = *acharcode + 1;
152     FT_UInt       result    = 0;
153 
154 
155     min = 0;
156     max = cmap->num_encodings;
157 
158     while ( min < max )
159     {
160       FT_ULong  code;
161 
162 
163       mid  = ( min + max ) >> 1;
164       code = encodings[mid].enc;
165 
166       if ( charcode == code )
167       {
168         result = encodings[mid].glyph;
169         goto Exit;
170       }
171 
172       if ( charcode < code )
173         max = mid;
174       else
175         min = mid + 1;
176     }
177 
178     charcode = 0;
179     if ( min < cmap->num_encodings )
180     {
181       charcode = encodings[min].enc;
182       result   = encodings[min].glyph;
183     }
184 
185   Exit:
186     if ( charcode > 0xFFFFFFFFUL )
187     {
188       FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
189       *acharcode = 0;
190       /* XXX: result should be changed to indicate an overflow error */
191     }
192     else
193       *acharcode = (FT_UInt32)charcode;
194 
195     return result;
196   }
197 
198 
199   static
200   const FT_CMap_ClassRec  pcf_cmap_class =
201   {
202     sizeof ( PCF_CMapRec ),
203     pcf_cmap_init,
204     pcf_cmap_done,
205     pcf_cmap_char_index,
206     pcf_cmap_char_next,
207 
208     NULL, NULL, NULL, NULL, NULL
209   };
210 
211 
212   FT_CALLBACK_DEF( void )
PCF_Face_Done(FT_Face pcfface)213   PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
214   {
215     PCF_Face   face = (PCF_Face)pcfface;
216     FT_Memory  memory;
217 
218 
219     if ( !face )
220       return;
221 
222     memory = FT_FACE_MEMORY( face );
223 
224     FT_FREE( face->encodings );
225     FT_FREE( face->metrics );
226 
227     /* free properties */
228     if ( face->properties )
229     {
230       FT_Int  i;
231 
232 
233       for ( i = 0; i < face->nprops; i++ )
234       {
235         PCF_Property  prop = &face->properties[i];
236 
237 
238         if ( prop )
239         {
240           FT_FREE( prop->name );
241           if ( prop->isString )
242             FT_FREE( prop->value.atom );
243         }
244       }
245 
246       FT_FREE( face->properties );
247     }
248 
249     FT_FREE( face->toc.tables );
250     FT_FREE( pcfface->family_name );
251     FT_FREE( pcfface->style_name );
252     FT_FREE( pcfface->available_sizes );
253     FT_FREE( face->charset_encoding );
254     FT_FREE( face->charset_registry );
255 
256     /* close compressed stream if any */
257     if ( pcfface->stream == &face->comp_stream )
258     {
259       FT_Stream_Close( &face->comp_stream );
260       pcfface->stream = face->comp_source;
261     }
262   }
263 
264 
265   FT_CALLBACK_DEF( FT_Error )
PCF_Face_Init(FT_Stream stream,FT_Face pcfface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)266   PCF_Face_Init( FT_Stream      stream,
267                  FT_Face        pcfface,        /* PCF_Face */
268                  FT_Int         face_index,
269                  FT_Int         num_params,
270                  FT_Parameter*  params )
271   {
272     PCF_Face  face  = (PCF_Face)pcfface;
273     FT_Error  error;
274 
275     FT_UNUSED( num_params );
276     FT_UNUSED( params );
277 
278 
279     FT_TRACE2(( "PCF driver\n" ));
280 
281     error = pcf_load_font( stream, face, face_index );
282     if ( error )
283     {
284       PCF_Face_Done( pcfface );
285 
286 #if defined( FT_CONFIG_OPTION_USE_ZLIB )  || \
287     defined( FT_CONFIG_OPTION_USE_LZW )   || \
288     defined( FT_CONFIG_OPTION_USE_BZIP2 )
289 
290 #ifdef FT_CONFIG_OPTION_USE_ZLIB
291       {
292         FT_Error  error2;
293 
294 
295         /* this didn't work, try gzip support! */
296         FT_TRACE2(( "  ... try gzip stream\n" ));
297         error2 = FT_Stream_OpenGzip( &face->comp_stream, stream );
298         if ( FT_ERR_EQ( error2, Unimplemented_Feature ) )
299           goto Fail;
300 
301         error = error2;
302       }
303 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
304 
305 #ifdef FT_CONFIG_OPTION_USE_LZW
306       if ( error )
307       {
308         FT_Error  error3;
309 
310 
311         /* this didn't work, try LZW support! */
312         FT_TRACE2(( "  ... try LZW stream\n" ));
313         error3 = FT_Stream_OpenLZW( &face->comp_stream, stream );
314         if ( FT_ERR_EQ( error3, Unimplemented_Feature ) )
315           goto Fail;
316 
317         error = error3;
318       }
319 #endif /* FT_CONFIG_OPTION_USE_LZW */
320 
321 #ifdef FT_CONFIG_OPTION_USE_BZIP2
322       if ( error )
323       {
324         FT_Error  error4;
325 
326 
327         /* this didn't work, try Bzip2 support! */
328         FT_TRACE2(( "  ... try Bzip2 stream\n" ));
329         error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream );
330         if ( FT_ERR_EQ( error4, Unimplemented_Feature ) )
331           goto Fail;
332 
333         error = error4;
334       }
335 #endif /* FT_CONFIG_OPTION_USE_BZIP2 */
336 
337       if ( error )
338         goto Fail;
339 
340       face->comp_source = stream;
341       pcfface->stream   = &face->comp_stream;
342 
343       stream = pcfface->stream;
344 
345       error = pcf_load_font( stream, face, face_index );
346       if ( error )
347         goto Fail;
348 
349 #else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
350            FT_CONFIG_OPTION_USE_LZW ||
351            FT_CONFIG_OPTION_USE_BZIP2) */
352 
353       goto Fail;
354 
355 #endif
356     }
357 
358     /* PCF cannot have multiple faces in a single font file.
359      * XXX: A non-zero face_index is already an invalid argument, but
360      *      Type1, Type42 drivers have a convention to return
361      *      an invalid argument error when the font could be
362      *      opened by the specified driver.
363      */
364     if ( face_index < 0 )
365       goto Exit;
366     else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
367     {
368       FT_ERROR(( "PCF_Face_Init: invalid face index\n" ));
369       PCF_Face_Done( pcfface );
370       return FT_THROW( Invalid_Argument );
371     }
372 
373     /* set up charmap */
374     {
375       FT_String  *charset_registry = face->charset_registry;
376       FT_String  *charset_encoding = face->charset_encoding;
377       FT_Bool     unicode_charmap  = 0;
378 
379 
380       if ( charset_registry && charset_encoding )
381       {
382         char*  s = charset_registry;
383 
384 
385         /* Uh, oh, compare first letters manually to avoid dependency
386            on locales. */
387         if ( ( s[0] == 'i' || s[0] == 'I' ) &&
388              ( s[1] == 's' || s[1] == 'S' ) &&
389              ( s[2] == 'o' || s[2] == 'O' ) )
390         {
391           s += 3;
392           if ( !ft_strcmp( s, "10646" )                      ||
393                ( !ft_strcmp( s, "8859" ) &&
394                  !ft_strcmp( face->charset_encoding, "1" ) ) )
395             unicode_charmap = 1;
396           /* another name for ASCII */
397           else if ( !ft_strcmp( s, "646.1991" )                 &&
398                     !ft_strcmp( face->charset_encoding, "IRV" ) )
399             unicode_charmap = 1;
400         }
401       }
402 
403       {
404         FT_CharMapRec  charmap;
405 
406 
407         charmap.face        = FT_FACE( face );
408         charmap.encoding    = FT_ENCODING_NONE;
409         /* initial platform/encoding should indicate unset status? */
410         charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
411         charmap.encoding_id = TT_APPLE_ID_DEFAULT;
412 
413         if ( unicode_charmap )
414         {
415           charmap.encoding    = FT_ENCODING_UNICODE;
416           charmap.platform_id = TT_PLATFORM_MICROSOFT;
417           charmap.encoding_id = TT_MS_ID_UNICODE_CS;
418         }
419 
420         error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
421       }
422     }
423 
424   Exit:
425     return error;
426 
427   Fail:
428     FT_TRACE2(( "  not a PCF file\n" ));
429     PCF_Face_Done( pcfface );
430     error = FT_THROW( Unknown_File_Format );  /* error */
431     goto Exit;
432   }
433 
434 
435   FT_CALLBACK_DEF( FT_Error )
PCF_Size_Select(FT_Size size,FT_ULong strike_index)436   PCF_Size_Select( FT_Size   size,
437                    FT_ULong  strike_index )
438   {
439     PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
440 
441 
442     FT_Select_Metrics( size->face, strike_index );
443 
444     size->metrics.ascender    =  accel->fontAscent * 64;
445     size->metrics.descender   = -accel->fontDescent * 64;
446     size->metrics.max_advance =  accel->maxbounds.characterWidth * 64;
447 
448     return FT_Err_Ok;
449   }
450 
451 
452   FT_CALLBACK_DEF( FT_Error )
PCF_Size_Request(FT_Size size,FT_Size_Request req)453   PCF_Size_Request( FT_Size          size,
454                     FT_Size_Request  req )
455   {
456     PCF_Face         face  = (PCF_Face)size->face;
457     FT_Bitmap_Size*  bsize = size->face->available_sizes;
458     FT_Error         error = FT_ERR( Invalid_Pixel_Size );
459     FT_Long          height;
460 
461 
462     height = FT_REQUEST_HEIGHT( req );
463     height = ( height + 32 ) >> 6;
464 
465     switch ( req->type )
466     {
467     case FT_SIZE_REQUEST_TYPE_NOMINAL:
468       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
469         error = FT_Err_Ok;
470       break;
471 
472     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
473       if ( height == ( face->accel.fontAscent +
474                        face->accel.fontDescent ) )
475         error = FT_Err_Ok;
476       break;
477 
478     default:
479       error = FT_THROW( Unimplemented_Feature );
480       break;
481     }
482 
483     if ( error )
484       return error;
485     else
486       return PCF_Size_Select( size, 0 );
487   }
488 
489 
490   FT_CALLBACK_DEF( FT_Error )
PCF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)491   PCF_Glyph_Load( FT_GlyphSlot  slot,
492                   FT_Size       size,
493                   FT_UInt       glyph_index,
494                   FT_Int32      load_flags )
495   {
496     PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
497     FT_Stream   stream;
498     FT_Error    error  = FT_Err_Ok;
499     FT_Bitmap*  bitmap = &slot->bitmap;
500     PCF_Metric  metric;
501     FT_ULong    bytes;
502 
503 
504     FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index ));
505 
506     if ( !face )
507     {
508       error = FT_THROW( Invalid_Face_Handle );
509       goto Exit;
510     }
511 
512     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
513     {
514       error = FT_THROW( Invalid_Argument );
515       goto Exit;
516     }
517 
518     stream = face->root.stream;
519 
520     metric = face->metrics + glyph_index;
521 
522     bitmap->rows       = (unsigned int)( metric->ascent +
523                                          metric->descent );
524     bitmap->width      = (unsigned int)( metric->rightSideBearing -
525                                          metric->leftSideBearing );
526     bitmap->num_grays  = 1;
527     bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
528 
529     switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
530     {
531     case 1:
532       bitmap->pitch = (int)( ( bitmap->width + 7 ) >> 3 );
533       break;
534 
535     case 2:
536       bitmap->pitch = (int)( ( ( bitmap->width + 15 ) >> 4 ) << 1 );
537       break;
538 
539     case 4:
540       bitmap->pitch = (int)( ( ( bitmap->width + 31 ) >> 5 ) << 2 );
541       break;
542 
543     case 8:
544       bitmap->pitch = (int)( ( ( bitmap->width + 63 ) >> 6 ) << 3 );
545       break;
546 
547     default:
548       return FT_THROW( Invalid_File_Format );
549     }
550 
551     slot->format      = FT_GLYPH_FORMAT_BITMAP;
552     slot->bitmap_left = metric->leftSideBearing;
553     slot->bitmap_top  = metric->ascent;
554 
555     slot->metrics.horiAdvance  = (FT_Pos)( metric->characterWidth * 64 );
556     slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 );
557     slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 );
558     slot->metrics.width        = (FT_Pos)( ( metric->rightSideBearing -
559                                              metric->leftSideBearing ) * 64 );
560     slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
561 
562     ft_synthesize_vertical_metrics( &slot->metrics,
563                                     ( face->accel.fontAscent +
564                                       face->accel.fontDescent ) * 64 );
565 
566     if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY )
567       goto Exit;
568 
569     /* XXX: to do: are there cases that need repadding the bitmap? */
570     bytes = (FT_ULong)bitmap->pitch * bitmap->rows;
571 
572     error = ft_glyphslot_alloc_bitmap( slot, (FT_ULong)bytes );
573     if ( error )
574       goto Exit;
575 
576     if ( FT_STREAM_SEEK( metric->bits )          ||
577          FT_STREAM_READ( bitmap->buffer, bytes ) )
578       goto Exit;
579 
580     if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
581       BitOrderInvert( bitmap->buffer, bytes );
582 
583     if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
584            PCF_BIT_ORDER( face->bitmapsFormat )  ) )
585     {
586       switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
587       {
588       case 1:
589         break;
590 
591       case 2:
592         TwoByteSwap( bitmap->buffer, bytes );
593         break;
594 
595       case 4:
596         FourByteSwap( bitmap->buffer, bytes );
597         break;
598       }
599     }
600 
601   Exit:
602     return error;
603   }
604 
605 
606   /*
607    *
608    * BDF SERVICE
609    *
610    */
611 
612   static FT_Error
pcf_get_bdf_property(PCF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)613   pcf_get_bdf_property( PCF_Face          face,
614                         const char*       prop_name,
615                         BDF_PropertyRec  *aproperty )
616   {
617     PCF_Property  prop;
618 
619 
620     prop = pcf_find_property( face, prop_name );
621     if ( prop )
622     {
623       if ( prop->isString )
624       {
625         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
626         aproperty->u.atom = prop->value.atom;
627       }
628       else
629       {
630         if ( prop->value.l > 0x7FFFFFFFL          ||
631              prop->value.l < ( -1 - 0x7FFFFFFFL ) )
632         {
633           FT_TRACE1(( "pcf_get_bdf_property:" ));
634           FT_TRACE1(( " too large integer 0x%x is truncated\n" ));
635         }
636 
637         /*
638          * The PCF driver loads all properties as signed integers.
639          * This really doesn't seem to be a problem, because this is
640          * sufficient for any meaningful values.
641          */
642         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
643         aproperty->u.integer = (FT_Int32)prop->value.l;
644       }
645 
646       return FT_Err_Ok;
647     }
648 
649     return FT_THROW( Invalid_Argument );
650   }
651 
652 
653   static FT_Error
pcf_get_charset_id(PCF_Face face,const char ** acharset_encoding,const char ** acharset_registry)654   pcf_get_charset_id( PCF_Face      face,
655                       const char*  *acharset_encoding,
656                       const char*  *acharset_registry )
657   {
658     *acharset_encoding = face->charset_encoding;
659     *acharset_registry = face->charset_registry;
660 
661     return FT_Err_Ok;
662   }
663 
664 
665   static const FT_Service_BDFRec  pcf_service_bdf =
666   {
667     (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,     /* get_charset_id */
668     (FT_BDF_GetPropertyFunc) pcf_get_bdf_property    /* get_property   */
669   };
670 
671 
672   /*
673    * PROPERTY SERVICE
674    *
675    */
676   static FT_Error
pcf_property_set(FT_Module module,const char * property_name,const void * value,FT_Bool value_is_string)677   pcf_property_set( FT_Module    module,         /* PCF_Driver */
678                     const char*  property_name,
679                     const void*  value,
680                     FT_Bool      value_is_string )
681   {
682 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
683 
684     FT_Error    error  = FT_Err_Ok;
685     PCF_Driver  driver = (PCF_Driver)module;
686 
687 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
688     FT_UNUSED( value_is_string );
689 #endif
690 
691 
692     if ( !ft_strcmp( property_name, "no-long-family-names" ) )
693     {
694 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
695       if ( value_is_string )
696       {
697         const char*  s   = (const char*)value;
698         long         lfn = ft_strtol( s, NULL, 10 );
699 
700 
701         if ( lfn == 0 )
702           driver->no_long_family_names = 0;
703         else if ( lfn == 1 )
704           driver->no_long_family_names = 1;
705         else
706           return FT_THROW( Invalid_Argument );
707       }
708       else
709 #endif
710       {
711         FT_Bool*  no_long_family_names = (FT_Bool*)value;
712 
713 
714         driver->no_long_family_names = *no_long_family_names;
715       }
716 
717       return error;
718     }
719 
720 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
721 
722     FT_UNUSED( module );
723     FT_UNUSED( value );
724     FT_UNUSED( value_is_string );
725 #ifndef FT_DEBUG_LEVEL_TRACE
726     FT_UNUSED( property_name );
727 #endif
728 
729 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
730 
731     FT_TRACE0(( "pcf_property_set: missing property `%s'\n",
732                 property_name ));
733     return FT_THROW( Missing_Property );
734   }
735 
736 
737   static FT_Error
pcf_property_get(FT_Module module,const char * property_name,const void * value)738   pcf_property_get( FT_Module    module,         /* PCF_Driver */
739                     const char*  property_name,
740                     const void*  value )
741   {
742 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
743 
744     FT_Error    error  = FT_Err_Ok;
745     PCF_Driver  driver = (PCF_Driver)module;
746 
747 
748     if ( !ft_strcmp( property_name, "no-long-family-names" ) )
749     {
750       FT_Bool   no_long_family_names = driver->no_long_family_names;
751       FT_Bool*  val                  = (FT_Bool*)value;
752 
753 
754       *val = no_long_family_names;
755 
756       return error;
757     }
758 
759 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
760 
761     FT_UNUSED( module );
762     FT_UNUSED( value );
763 #ifndef FT_DEBUG_LEVEL_TRACE
764     FT_UNUSED( property_name );
765 #endif
766 
767 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
768 
769     FT_TRACE0(( "pcf_property_get: missing property `%s'\n",
770                 property_name ));
771     return FT_THROW( Missing_Property );
772   }
773 
774 
775   FT_DEFINE_SERVICE_PROPERTIESREC(
776     pcf_service_properties,
777 
778     (FT_Properties_SetFunc)pcf_property_set,      /* set_property */
779     (FT_Properties_GetFunc)pcf_property_get )     /* get_property */
780 
781 
782   /*
783    *
784    * SERVICE LIST
785    *
786    */
787 
788   static const FT_ServiceDescRec  pcf_services[] =
789   {
790     { FT_SERVICE_ID_BDF,         &pcf_service_bdf },
791     { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF },
792     { FT_SERVICE_ID_PROPERTIES,  &pcf_service_properties },
793     { NULL, NULL }
794   };
795 
796 
797   FT_CALLBACK_DEF( FT_Module_Interface )
pcf_driver_requester(FT_Module module,const char * name)798   pcf_driver_requester( FT_Module    module,
799                         const char*  name )
800   {
801     FT_UNUSED( module );
802 
803     return ft_service_list_lookup( pcf_services, name );
804   }
805 
806 
807   FT_CALLBACK_DEF( FT_Error )
pcf_driver_init(FT_Module module)808   pcf_driver_init( FT_Module  module )      /* PCF_Driver */
809   {
810 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
811     PCF_Driver  driver = (PCF_Driver)module;
812 
813 
814     driver->no_long_family_names = 0;
815 #else
816     FT_UNUSED( module );
817 #endif
818 
819     return FT_Err_Ok;
820   }
821 
822 
823   FT_CALLBACK_DEF( void )
pcf_driver_done(FT_Module module)824   pcf_driver_done( FT_Module  module )      /* PCF_Driver */
825   {
826     FT_UNUSED( module );
827   }
828 
829 
830   FT_CALLBACK_TABLE_DEF
831   const FT_Driver_ClassRec  pcf_driver_class =
832   {
833     {
834       FT_MODULE_FONT_DRIVER        |
835       FT_MODULE_DRIVER_NO_OUTLINES,
836 
837       sizeof ( PCF_DriverRec ),
838       "pcf",
839       0x10000L,
840       0x20000L,
841 
842       NULL,   /* module-specific interface */
843 
844       pcf_driver_init,          /* FT_Module_Constructor  module_init   */
845       pcf_driver_done,          /* FT_Module_Destructor   module_done   */
846       pcf_driver_requester      /* FT_Module_Requester    get_interface */
847     },
848 
849     sizeof ( PCF_FaceRec ),
850     sizeof ( FT_SizeRec ),
851     sizeof ( FT_GlyphSlotRec ),
852 
853     PCF_Face_Init,              /* FT_Face_InitFunc  init_face */
854     PCF_Face_Done,              /* FT_Face_DoneFunc  done_face */
855     NULL,                       /* FT_Size_InitFunc  init_size */
856     NULL,                       /* FT_Size_DoneFunc  done_size */
857     NULL,                       /* FT_Slot_InitFunc  init_slot */
858     NULL,                       /* FT_Slot_DoneFunc  done_slot */
859 
860     PCF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
861 
862     NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
863     NULL,                       /* FT_Face_AttachFunc       attach_file  */
864     NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
865 
866     PCF_Size_Request,           /* FT_Size_RequestFunc  request_size */
867     PCF_Size_Select             /* FT_Size_SelectFunc   select_size  */
868   };
869 
870 
871 /* END */
872