• 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 
29 #include <freetype/internal/ftdebug.h>
30 #include <freetype/internal/ftstream.h>
31 #include <freetype/internal/ftobjs.h>
32 #include <freetype/ftgzip.h>
33 #include <freetype/ftlzw.h>
34 #include <freetype/ftbzip2.h>
35 #include <freetype/fterrors.h>
36 #include <freetype/ftbdf.h>
37 #include <freetype/ttnameid.h>
38 
39 #include "pcf.h"
40 #include "pcfdrivr.h"
41 #include "pcfread.h"
42 
43 #include "pcferror.h"
44 #include "pcfutil.h"
45 
46 #undef  FT_COMPONENT
47 #define FT_COMPONENT  pcfread
48 
49 #include <freetype/internal/services/svbdf.h>
50 #include <freetype/internal/services/svfntfmt.h>
51 #include <freetype/internal/services/svprop.h>
52 #include <freetype/ftdriver.h>
53 
54 
55   /**************************************************************************
56    *
57    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
58    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
59    * messages during execution.
60    */
61 #undef  FT_COMPONENT
62 #define FT_COMPONENT  pcfdriver
63 
64 
65   /*
66    * This file uses X11 terminology for PCF data; an `encoding' in X11 speak
67    * is the same as a `character code' in FreeType speak.
68    */
69   typedef struct  PCF_CMapRec_
70   {
71     FT_CMapRec  root;
72     PCF_Enc     enc;
73 
74   } PCF_CMapRec, *PCF_CMap;
75 
76 
77   FT_CALLBACK_DEF( FT_Error )
pcf_cmap_init(FT_CMap pcfcmap,FT_Pointer init_data)78   pcf_cmap_init( FT_CMap     pcfcmap,   /* PCF_CMap */
79                  FT_Pointer  init_data )
80   {
81     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
82     PCF_Face  face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
83 
84     FT_UNUSED( init_data );
85 
86 
87     cmap->enc = &face->enc;
88 
89     return FT_Err_Ok;
90   }
91 
92 
93   FT_CALLBACK_DEF( void )
pcf_cmap_done(FT_CMap pcfcmap)94   pcf_cmap_done( FT_CMap  pcfcmap )         /* PCF_CMap */
95   {
96     PCF_CMap  cmap = (PCF_CMap)pcfcmap;
97 
98 
99     cmap->enc = NULL;
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_Enc    enc  = cmap->enc;
109     FT_UShort  charcodeRow;
110     FT_UShort  charcodeCol;
111 
112 
113     if ( charcode > (FT_UInt32)( enc->lastRow  * 256 + enc->lastCol  ) ||
114          charcode < (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ) )
115       return 0;
116 
117     charcodeRow = (FT_UShort)( charcode >> 8 );
118     charcodeCol = (FT_UShort)( charcode & 0xFF );
119 
120     if ( charcodeCol < enc->firstCol ||
121          charcodeCol > enc->lastCol  )
122       return 0;
123 
124     return (FT_UInt)enc->offset[( charcodeRow - enc->firstRow ) *
125                                   ( enc->lastCol - enc->firstCol + 1 ) +
126                                 charcodeCol - enc->firstCol];
127   }
128 
129 
130   FT_CALLBACK_DEF( FT_UInt )
pcf_cmap_char_next(FT_CMap pcfcmap,FT_UInt32 * acharcode)131   pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
132                       FT_UInt32  *acharcode )
133   {
134     PCF_CMap   cmap      = (PCF_CMap)pcfcmap;
135     PCF_Enc    enc       = cmap->enc;
136     FT_UInt32  charcode  = *acharcode;
137     FT_UShort  charcodeRow;
138     FT_UShort  charcodeCol;
139     FT_UInt    result = 0;
140 
141 
142     while ( charcode < (FT_UInt32)( enc->lastRow * 256 + enc->lastCol ) )
143     {
144       charcode++;
145 
146       if ( charcode < (FT_UInt32)( enc->firstRow * 256 + enc->firstCol ) )
147         charcode = (FT_UInt32)( enc->firstRow * 256 + enc->firstCol );
148 
149       charcodeRow = (FT_UShort)( charcode >> 8 );
150       charcodeCol = (FT_UShort)( charcode & 0xFF );
151 
152       if ( charcodeCol < enc->firstCol )
153         charcodeCol = enc->firstCol;
154       else if ( charcodeCol > enc->lastCol )
155       {
156         charcodeRow++;
157         charcodeCol = enc->firstCol;
158       }
159 
160       charcode = (FT_UInt32)( charcodeRow * 256 + charcodeCol );
161 
162       result = (FT_UInt)enc->offset[( charcodeRow - enc->firstRow ) *
163                                       ( enc->lastCol - enc->firstCol + 1 ) +
164                                     charcodeCol - enc->firstCol];
165       if ( result != 0xFFFFU )
166         break;
167     }
168 
169     *acharcode = charcode;
170 
171     return result;
172   }
173 
174 
175   static
176   const FT_CMap_ClassRec  pcf_cmap_class =
177   {
178     sizeof ( PCF_CMapRec ),
179     pcf_cmap_init,
180     pcf_cmap_done,
181     pcf_cmap_char_index,
182     pcf_cmap_char_next,
183 
184     NULL, NULL, NULL, NULL, NULL
185   };
186 
187 
188   FT_CALLBACK_DEF( void )
PCF_Face_Done(FT_Face pcfface)189   PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
190   {
191     PCF_Face   face = (PCF_Face)pcfface;
192     FT_Memory  memory;
193 
194 
195     if ( !face )
196       return;
197 
198     memory = FT_FACE_MEMORY( face );
199 
200     FT_FREE( face->metrics );
201     FT_FREE( face->enc.offset );
202 
203     /* free properties */
204     if ( face->properties )
205     {
206       FT_Int  i;
207 
208 
209       for ( i = 0; i < face->nprops; i++ )
210       {
211         PCF_Property  prop = &face->properties[i];
212 
213 
214         if ( prop )
215         {
216           FT_FREE( prop->name );
217           if ( prop->isString )
218             FT_FREE( prop->value.atom );
219         }
220       }
221 
222       FT_FREE( face->properties );
223     }
224 
225     FT_FREE( face->toc.tables );
226     FT_FREE( pcfface->family_name );
227     FT_FREE( pcfface->style_name );
228     FT_FREE( pcfface->available_sizes );
229     FT_FREE( face->charset_encoding );
230     FT_FREE( face->charset_registry );
231 
232     /* close compressed stream if any */
233     if ( pcfface->stream == &face->comp_stream )
234     {
235       FT_Stream_Close( &face->comp_stream );
236       pcfface->stream = face->comp_source;
237     }
238   }
239 
240 
241   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)242   PCF_Face_Init( FT_Stream      stream,
243                  FT_Face        pcfface,        /* PCF_Face */
244                  FT_Int         face_index,
245                  FT_Int         num_params,
246                  FT_Parameter*  params )
247   {
248     PCF_Face  face  = (PCF_Face)pcfface;
249     FT_Error  error;
250 
251     FT_UNUSED( num_params );
252     FT_UNUSED( params );
253 
254 
255     FT_TRACE2(( "PCF driver\n" ));
256 
257     error = pcf_load_font( stream, face, face_index );
258     if ( error )
259     {
260       PCF_Face_Done( pcfface );
261 
262 #if defined( FT_CONFIG_OPTION_USE_ZLIB )  || \
263     defined( FT_CONFIG_OPTION_USE_LZW )   || \
264     defined( FT_CONFIG_OPTION_USE_BZIP2 )
265 
266 #ifdef FT_CONFIG_OPTION_USE_ZLIB
267       {
268         FT_Error  error2;
269 
270 
271         /* this didn't work, try gzip support! */
272         FT_TRACE2(( "  ... try gzip stream\n" ));
273         error2 = FT_Stream_OpenGzip( &face->comp_stream, stream );
274         if ( FT_ERR_EQ( error2, Unimplemented_Feature ) )
275           goto Fail;
276 
277         error = error2;
278       }
279 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
280 
281 #ifdef FT_CONFIG_OPTION_USE_LZW
282       if ( error )
283       {
284         FT_Error  error3;
285 
286 
287         /* this didn't work, try LZW support! */
288         FT_TRACE2(( "  ... try LZW stream\n" ));
289         error3 = FT_Stream_OpenLZW( &face->comp_stream, stream );
290         if ( FT_ERR_EQ( error3, Unimplemented_Feature ) )
291           goto Fail;
292 
293         error = error3;
294       }
295 #endif /* FT_CONFIG_OPTION_USE_LZW */
296 
297 #ifdef FT_CONFIG_OPTION_USE_BZIP2
298       if ( error )
299       {
300         FT_Error  error4;
301 
302 
303         /* this didn't work, try Bzip2 support! */
304         FT_TRACE2(( "  ... try Bzip2 stream\n" ));
305         error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream );
306         if ( FT_ERR_EQ( error4, Unimplemented_Feature ) )
307           goto Fail;
308 
309         error = error4;
310       }
311 #endif /* FT_CONFIG_OPTION_USE_BZIP2 */
312 
313       if ( error )
314         goto Fail;
315 
316       face->comp_source = stream;
317       pcfface->stream   = &face->comp_stream;
318 
319       stream = pcfface->stream;
320 
321       error = pcf_load_font( stream, face, face_index );
322       if ( error )
323         goto Fail;
324 
325 #else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
326            FT_CONFIG_OPTION_USE_LZW ||
327            FT_CONFIG_OPTION_USE_BZIP2) */
328 
329       goto Fail;
330 
331 #endif
332     }
333 
334     /* PCF cannot have multiple faces in a single font file.
335      * XXX: A non-zero face_index is already an invalid argument, but
336      *      Type1, Type42 drivers have a convention to return
337      *      an invalid argument error when the font could be
338      *      opened by the specified driver.
339      */
340     if ( face_index < 0 )
341       goto Exit;
342     else if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
343     {
344       FT_ERROR(( "PCF_Face_Init: invalid face index\n" ));
345       PCF_Face_Done( pcfface );
346       return FT_THROW( Invalid_Argument );
347     }
348 
349     /* set up charmap */
350     {
351       FT_String  *charset_registry = face->charset_registry;
352       FT_String  *charset_encoding = face->charset_encoding;
353       FT_Bool     unicode_charmap  = 0;
354 
355 
356       if ( charset_registry && charset_encoding )
357       {
358         char*  s = charset_registry;
359 
360 
361         /* Uh, oh, compare first letters manually to avoid dependency
362            on locales. */
363         if ( ( s[0] == 'i' || s[0] == 'I' ) &&
364              ( s[1] == 's' || s[1] == 'S' ) &&
365              ( s[2] == 'o' || s[2] == 'O' ) )
366         {
367           s += 3;
368           if ( !ft_strcmp( s, "10646" )                      ||
369                ( !ft_strcmp( s, "8859" ) &&
370                  !ft_strcmp( face->charset_encoding, "1" ) ) )
371             unicode_charmap = 1;
372           /* another name for ASCII */
373           else if ( !ft_strcmp( s, "646.1991" )                 &&
374                     !ft_strcmp( face->charset_encoding, "IRV" ) )
375             unicode_charmap = 1;
376         }
377       }
378 
379       {
380         FT_CharMapRec  charmap;
381 
382 
383         charmap.face        = FT_FACE( face );
384         charmap.encoding    = FT_ENCODING_NONE;
385         /* initial platform/encoding should indicate unset status? */
386         charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
387         charmap.encoding_id = TT_APPLE_ID_DEFAULT;
388 
389         if ( unicode_charmap )
390         {
391           charmap.encoding    = FT_ENCODING_UNICODE;
392           charmap.platform_id = TT_PLATFORM_MICROSOFT;
393           charmap.encoding_id = TT_MS_ID_UNICODE_CS;
394         }
395 
396         error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
397       }
398     }
399 
400   Exit:
401     return error;
402 
403   Fail:
404     FT_TRACE2(( "  not a PCF file\n" ));
405     PCF_Face_Done( pcfface );
406     error = FT_THROW( Unknown_File_Format );  /* error */
407     goto Exit;
408   }
409 
410 
411   FT_CALLBACK_DEF( FT_Error )
PCF_Size_Select(FT_Size size,FT_ULong strike_index)412   PCF_Size_Select( FT_Size   size,
413                    FT_ULong  strike_index )
414   {
415     PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
416 
417 
418     FT_Select_Metrics( size->face, strike_index );
419 
420     size->metrics.ascender    =  accel->fontAscent * 64;
421     size->metrics.descender   = -accel->fontDescent * 64;
422     size->metrics.max_advance =  accel->maxbounds.characterWidth * 64;
423 
424     return FT_Err_Ok;
425   }
426 
427 
428   FT_CALLBACK_DEF( FT_Error )
PCF_Size_Request(FT_Size size,FT_Size_Request req)429   PCF_Size_Request( FT_Size          size,
430                     FT_Size_Request  req )
431   {
432     PCF_Face         face  = (PCF_Face)size->face;
433     FT_Bitmap_Size*  bsize = size->face->available_sizes;
434     FT_Error         error = FT_ERR( Invalid_Pixel_Size );
435     FT_Long          height;
436 
437 
438     height = FT_REQUEST_HEIGHT( req );
439     height = ( height + 32 ) >> 6;
440 
441     switch ( req->type )
442     {
443     case FT_SIZE_REQUEST_TYPE_NOMINAL:
444       if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
445         error = FT_Err_Ok;
446       break;
447 
448     case FT_SIZE_REQUEST_TYPE_REAL_DIM:
449       if ( height == ( face->accel.fontAscent +
450                        face->accel.fontDescent ) )
451         error = FT_Err_Ok;
452       break;
453 
454     default:
455       error = FT_THROW( Unimplemented_Feature );
456       break;
457     }
458 
459     if ( error )
460       return error;
461     else
462       return PCF_Size_Select( size, 0 );
463   }
464 
465 
466   FT_CALLBACK_DEF( FT_Error )
PCF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)467   PCF_Glyph_Load( FT_GlyphSlot  slot,
468                   FT_Size       size,
469                   FT_UInt       glyph_index,
470                   FT_Int32      load_flags )
471   {
472     PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
473     FT_Stream   stream;
474     FT_Error    error  = FT_Err_Ok;
475     FT_Bitmap*  bitmap = &slot->bitmap;
476     PCF_Metric  metric;
477     FT_ULong    bytes;
478 
479 
480     FT_TRACE1(( "PCF_Glyph_Load: glyph index %d\n", glyph_index ));
481 
482     if ( !face )
483     {
484       error = FT_THROW( Invalid_Face_Handle );
485       goto Exit;
486     }
487 
488     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
489     {
490       error = FT_THROW( Invalid_Argument );
491       goto Exit;
492     }
493 
494     stream = face->root.stream;
495 
496     metric = face->metrics + glyph_index;
497 
498     bitmap->rows       = (unsigned int)( metric->ascent +
499                                          metric->descent );
500     bitmap->width      = (unsigned int)( metric->rightSideBearing -
501                                          metric->leftSideBearing );
502     bitmap->num_grays  = 1;
503     bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
504 
505     switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
506     {
507     case 1:
508       bitmap->pitch = (int)( ( bitmap->width + 7 ) >> 3 );
509       break;
510 
511     case 2:
512       bitmap->pitch = (int)( ( ( bitmap->width + 15 ) >> 4 ) << 1 );
513       break;
514 
515     case 4:
516       bitmap->pitch = (int)( ( ( bitmap->width + 31 ) >> 5 ) << 2 );
517       break;
518 
519     case 8:
520       bitmap->pitch = (int)( ( ( bitmap->width + 63 ) >> 6 ) << 3 );
521       break;
522 
523     default:
524       return FT_THROW( Invalid_File_Format );
525     }
526 
527     slot->format      = FT_GLYPH_FORMAT_BITMAP;
528     slot->bitmap_left = metric->leftSideBearing;
529     slot->bitmap_top  = metric->ascent;
530 
531     slot->metrics.horiAdvance  = (FT_Pos)( metric->characterWidth * 64 );
532     slot->metrics.horiBearingX = (FT_Pos)( metric->leftSideBearing * 64 );
533     slot->metrics.horiBearingY = (FT_Pos)( metric->ascent * 64 );
534     slot->metrics.width        = (FT_Pos)( ( metric->rightSideBearing -
535                                              metric->leftSideBearing ) * 64 );
536     slot->metrics.height       = (FT_Pos)( bitmap->rows * 64 );
537 
538     ft_synthesize_vertical_metrics( &slot->metrics,
539                                     ( face->accel.fontAscent +
540                                       face->accel.fontDescent ) * 64 );
541 
542     if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY )
543       goto Exit;
544 
545     /* XXX: to do: are there cases that need repadding the bitmap? */
546     bytes = (FT_ULong)bitmap->pitch * bitmap->rows;
547 
548     error = ft_glyphslot_alloc_bitmap( slot, (FT_ULong)bytes );
549     if ( error )
550       goto Exit;
551 
552     if ( FT_STREAM_SEEK( metric->bits )          ||
553          FT_STREAM_READ( bitmap->buffer, bytes ) )
554       goto Exit;
555 
556     if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
557       BitOrderInvert( bitmap->buffer, bytes );
558 
559     if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
560            PCF_BIT_ORDER( face->bitmapsFormat )  ) )
561     {
562       switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
563       {
564       case 1:
565         break;
566 
567       case 2:
568         TwoByteSwap( bitmap->buffer, bytes );
569         break;
570 
571       case 4:
572         FourByteSwap( bitmap->buffer, bytes );
573         break;
574       }
575     }
576 
577   Exit:
578     return error;
579   }
580 
581 
582   /*
583    *
584    * BDF SERVICE
585    *
586    */
587 
588   static FT_Error
pcf_get_bdf_property(PCF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)589   pcf_get_bdf_property( PCF_Face          face,
590                         const char*       prop_name,
591                         BDF_PropertyRec  *aproperty )
592   {
593     PCF_Property  prop;
594 
595 
596     prop = pcf_find_property( face, prop_name );
597     if ( prop )
598     {
599       if ( prop->isString )
600       {
601         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
602         aproperty->u.atom = prop->value.atom;
603       }
604       else
605       {
606         if ( prop->value.l > 0x7FFFFFFFL          ||
607              prop->value.l < ( -1 - 0x7FFFFFFFL ) )
608         {
609           FT_TRACE1(( "pcf_get_bdf_property:"
610                       " too large integer 0x%lx is truncated\n",
611                       prop->value.l ));
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