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