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