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