xref: /aosp_15_r20/external/freetype/src/pcf/pcfdrivr.c (revision 63949dbd25bcc50c4e1178497ff9e9574d44fc5a)
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 cmap,FT_Pointer init_data)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 )
pcf_cmap_done(FT_CMap cmap)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 )
pcf_cmap_char_index(FT_CMap cmap,FT_UInt32 charcode)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 )
pcf_cmap_char_next(FT_CMap cmap,FT_UInt32 * acharcode)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 )
PCF_Face_Done(FT_Face face)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 )
PCF_Face_Init(FT_Stream stream,FT_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)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 )
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   FT_CALLBACK_DEF( FT_Error )
pcf_get_bdf_property(FT_Face face,const char * prop_name,BDF_PropertyRec * aproperty)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 )
pcf_get_charset_id(FT_Face face,const char ** acharset_encoding,const char ** acharset_registry)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 )
pcf_property_set(FT_Module module,const char * property_name,const void * value,FT_Bool value_is_string)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 )
pcf_property_get(FT_Module module,const char * property_name,void * value)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 )
pcf_driver_requester(FT_Module module,const char * name)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 )
pcf_driver_init(FT_Module module)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 )
pcf_driver_done(FT_Module module)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 */
837