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
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in
16all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24THE 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 */
837