• 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_Enc  enc = ( (PCF_CMap)pcfcmap )->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 )
pcf_cmap_char_next(FT_CMap pcfcmap,FT_UInt32 * acharcode)124   pcf_cmap_char_next( FT_CMap    pcfcmap,   /* PCF_CMap */
125                       FT_UInt32  *acharcode )
126   {
127     PCF_Enc    enc = ( (PCF_CMap)pcfcmap )->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 )
PCF_Face_Done(FT_Face pcfface)173   PCF_Face_Done( FT_Face  pcfface )         /* PCF_Face */
174   {
175     PCF_Face   face = (PCF_Face)pcfface;
176     FT_Memory  memory;
177 
178 
179     if ( !face )
180       return;
181 
182     memory = FT_FACE_MEMORY( face );
183 
184     FT_FREE( face->metrics );
185     FT_FREE( face->enc.offset );
186 
187     /* free properties */
188     if ( face->properties )
189     {
190       FT_Int  i;
191 
192 
193       for ( i = 0; i < face->nprops; i++ )
194       {
195         PCF_Property  prop = &face->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( face->properties );
207     }
208 
209     FT_FREE( face->toc.tables );
210     FT_FREE( pcfface->family_name );
211     FT_FREE( pcfface->style_name );
212     FT_FREE( pcfface->available_sizes );
213     FT_FREE( face->charset_encoding );
214     FT_FREE( face->charset_registry );
215 
216     /* close compressed stream if any */
217     if ( pcfface->stream == &face->comp_stream )
218     {
219       FT_Stream_Close( &face->comp_stream );
220       pcfface->stream = face->comp_source;
221     }
222   }
223 
224 
225   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)226   PCF_Face_Init( FT_Stream      stream,
227                  FT_Face        pcfface,        /* PCF_Face */
228                  FT_Int         face_index,
229                  FT_Int         num_params,
230                  FT_Parameter*  params )
231   {
232     PCF_Face  face  = (PCF_Face)pcfface;
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, face, face_index );
242     if ( error )
243     {
244       PCF_Face_Done( pcfface );
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( &face->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( &face->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( &face->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       face->comp_source = stream;
301       pcfface->stream   = &face->comp_stream;
302 
303       stream = pcfface->stream;
304 
305       error = pcf_load_font( stream, face, 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( pcfface );
330       return FT_THROW( Invalid_Argument );
331     }
332 
333     /* set up charmap */
334     {
335       FT_String  *charset_registry = face->charset_registry;
336       FT_String  *charset_encoding = face->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( face->charset_encoding, "1" ) ) )
355             unicode_charmap = 1;
356           /* another name for ASCII */
357           else if ( !ft_strcmp( s, "646.1991" )                 &&
358                     !ft_strcmp( face->charset_encoding, "IRV" ) )
359             unicode_charmap = 1;
360         }
361       }
362 
363       {
364         FT_CharMapRec  charmap;
365 
366 
367         charmap.face        = FT_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( pcfface );
390     error = FT_THROW( Unknown_File_Format );  /* error */
391     goto Exit;
392   }
393 
394 
395   FT_CALLBACK_DEF( FT_Error )
PCF_Size_Select(FT_Size size,FT_ULong strike_index)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 )
PCF_Size_Request(FT_Size size,FT_Size_Request req)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 )
PCF_Glyph_Load(FT_GlyphSlot slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)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   static FT_Error
pcf_get_bdf_property(PCF_Face face,const char * prop_name,BDF_PropertyRec * aproperty)573   pcf_get_bdf_property( PCF_Face          face,
574                         const char*       prop_name,
575                         BDF_PropertyRec  *aproperty )
576   {
577     PCF_Property  prop;
578 
579 
580     prop = pcf_find_property( face, prop_name );
581     if ( prop )
582     {
583       if ( prop->isString )
584       {
585         aproperty->type   = BDF_PROPERTY_TYPE_ATOM;
586         aproperty->u.atom = prop->value.atom;
587       }
588       else
589       {
590         if ( prop->value.l > 0x7FFFFFFFL          ||
591              prop->value.l < ( -1 - 0x7FFFFFFFL ) )
592         {
593           FT_TRACE2(( "pcf_get_bdf_property:"
594                       " too large integer 0x%lx is truncated\n",
595                       prop->value.l ));
596         }
597 
598         /*
599          * The PCF driver loads all properties as signed integers.
600          * This really doesn't seem to be a problem, because this is
601          * sufficient for any meaningful values.
602          */
603         aproperty->type      = BDF_PROPERTY_TYPE_INTEGER;
604         aproperty->u.integer = (FT_Int32)prop->value.l;
605       }
606 
607       return FT_Err_Ok;
608     }
609 
610     return FT_THROW( Invalid_Argument );
611   }
612 
613 
614   static FT_Error
pcf_get_charset_id(PCF_Face face,const char ** acharset_encoding,const char ** acharset_registry)615   pcf_get_charset_id( PCF_Face      face,
616                       const char*  *acharset_encoding,
617                       const char*  *acharset_registry )
618   {
619     *acharset_encoding = face->charset_encoding;
620     *acharset_registry = face->charset_registry;
621 
622     return FT_Err_Ok;
623   }
624 
625 
626   static const FT_Service_BDFRec  pcf_service_bdf =
627   {
628     (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,     /* get_charset_id */
629     (FT_BDF_GetPropertyFunc) pcf_get_bdf_property    /* get_property   */
630   };
631 
632 
633   /*
634    * PROPERTY SERVICE
635    *
636    */
637   static FT_Error
pcf_property_set(FT_Module module,const char * property_name,const void * value,FT_Bool value_is_string)638   pcf_property_set( FT_Module    module,         /* PCF_Driver */
639                     const char*  property_name,
640                     const void*  value,
641                     FT_Bool      value_is_string )
642   {
643 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
644 
645     FT_Error    error  = FT_Err_Ok;
646     PCF_Driver  driver = (PCF_Driver)module;
647 
648 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
649     FT_UNUSED( value_is_string );
650 #endif
651 
652 
653     if ( !ft_strcmp( property_name, "no-long-family-names" ) )
654     {
655 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
656       if ( value_is_string )
657       {
658         const char*  s   = (const char*)value;
659         long         lfn = ft_strtol( s, NULL, 10 );
660 
661 
662         if ( lfn == 0 )
663           driver->no_long_family_names = 0;
664         else if ( lfn == 1 )
665           driver->no_long_family_names = 1;
666         else
667           return FT_THROW( Invalid_Argument );
668       }
669       else
670 #endif
671       {
672         FT_Bool*  no_long_family_names = (FT_Bool*)value;
673 
674 
675         driver->no_long_family_names = *no_long_family_names;
676       }
677 
678       return error;
679     }
680 
681 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
682 
683     FT_UNUSED( module );
684     FT_UNUSED( value );
685     FT_UNUSED( value_is_string );
686 #ifndef FT_DEBUG_LEVEL_TRACE
687     FT_UNUSED( property_name );
688 #endif
689 
690 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
691 
692     FT_TRACE2(( "pcf_property_set: missing property `%s'\n",
693                 property_name ));
694     return FT_THROW( Missing_Property );
695   }
696 
697 
698   static FT_Error
pcf_property_get(FT_Module module,const char * property_name,const void * value)699   pcf_property_get( FT_Module    module,         /* PCF_Driver */
700                     const char*  property_name,
701                     const void*  value )
702   {
703 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
704 
705     FT_Error    error  = FT_Err_Ok;
706     PCF_Driver  driver = (PCF_Driver)module;
707 
708 
709     if ( !ft_strcmp( property_name, "no-long-family-names" ) )
710     {
711       FT_Bool   no_long_family_names = driver->no_long_family_names;
712       FT_Bool*  val                  = (FT_Bool*)value;
713 
714 
715       *val = no_long_family_names;
716 
717       return error;
718     }
719 
720 #else /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
721 
722     FT_UNUSED( module );
723     FT_UNUSED( value );
724 #ifndef FT_DEBUG_LEVEL_TRACE
725     FT_UNUSED( property_name );
726 #endif
727 
728 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
729 
730     FT_TRACE2(( "pcf_property_get: missing property `%s'\n",
731                 property_name ));
732     return FT_THROW( Missing_Property );
733   }
734 
735 
736   FT_DEFINE_SERVICE_PROPERTIESREC(
737     pcf_service_properties,
738 
739     (FT_Properties_SetFunc)pcf_property_set,      /* set_property */
740     (FT_Properties_GetFunc)pcf_property_get )     /* get_property */
741 
742 
743   /*
744    *
745    * SERVICE LIST
746    *
747    */
748 
749   static const FT_ServiceDescRec  pcf_services[] =
750   {
751     { FT_SERVICE_ID_BDF,         &pcf_service_bdf },
752     { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_PCF },
753     { FT_SERVICE_ID_PROPERTIES,  &pcf_service_properties },
754     { NULL, NULL }
755   };
756 
757 
758   FT_CALLBACK_DEF( FT_Module_Interface )
pcf_driver_requester(FT_Module module,const char * name)759   pcf_driver_requester( FT_Module    module,
760                         const char*  name )
761   {
762     FT_UNUSED( module );
763 
764     return ft_service_list_lookup( pcf_services, name );
765   }
766 
767 
768   FT_CALLBACK_DEF( FT_Error )
pcf_driver_init(FT_Module module)769   pcf_driver_init( FT_Module  module )      /* PCF_Driver */
770   {
771 #ifdef PCF_CONFIG_OPTION_LONG_FAMILY_NAMES
772     PCF_Driver  driver = (PCF_Driver)module;
773 
774 
775     driver->no_long_family_names = 0;
776 #else
777     FT_UNUSED( module );
778 #endif
779 
780     return FT_Err_Ok;
781   }
782 
783 
784   FT_CALLBACK_DEF( void )
pcf_driver_done(FT_Module module)785   pcf_driver_done( FT_Module  module )      /* PCF_Driver */
786   {
787     FT_UNUSED( module );
788   }
789 
790 
791   FT_CALLBACK_TABLE_DEF
792   const FT_Driver_ClassRec  pcf_driver_class =
793   {
794     {
795       FT_MODULE_FONT_DRIVER        |
796       FT_MODULE_DRIVER_NO_OUTLINES,
797 
798       sizeof ( PCF_DriverRec ),
799       "pcf",
800       0x10000L,
801       0x20000L,
802 
803       NULL,   /* module-specific interface */
804 
805       pcf_driver_init,          /* FT_Module_Constructor  module_init   */
806       pcf_driver_done,          /* FT_Module_Destructor   module_done   */
807       pcf_driver_requester      /* FT_Module_Requester    get_interface */
808     },
809 
810     sizeof ( PCF_FaceRec ),
811     sizeof ( FT_SizeRec ),
812     sizeof ( FT_GlyphSlotRec ),
813 
814     PCF_Face_Init,              /* FT_Face_InitFunc  init_face */
815     PCF_Face_Done,              /* FT_Face_DoneFunc  done_face */
816     NULL,                       /* FT_Size_InitFunc  init_size */
817     NULL,                       /* FT_Size_DoneFunc  done_size */
818     NULL,                       /* FT_Slot_InitFunc  init_slot */
819     NULL,                       /* FT_Slot_DoneFunc  done_slot */
820 
821     PCF_Glyph_Load,             /* FT_Slot_LoadFunc  load_glyph */
822 
823     NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
824     NULL,                       /* FT_Face_AttachFunc       attach_file  */
825     NULL,                       /* FT_Face_GetAdvancesFunc  get_advances */
826 
827     PCF_Size_Request,           /* FT_Size_RequestFunc  request_size */
828     PCF_Size_Select             /* FT_Size_SelectFunc   select_size  */
829   };
830 
831 
832 /* END */
833