3 FreeType font driver for pcf files
5 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by
6 Francesco Zappa Nardelli
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:
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
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
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
46 #define FT_COMPONENT trace_pcfread
48 #include FT_SERVICE_BDF_H
49 #include FT_SERVICE_XFREE86_NAME_H
52 /*************************************************************************/
54 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
55 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
56 /* messages during execution. */
59 #define FT_COMPONENT trace_pcfdriver
62 typedef struct PCF_CMapRec_
65 FT_UInt num_encodings
;
66 PCF_Encoding encodings
;
68 } PCF_CMapRec
, *PCF_CMap
;
71 FT_CALLBACK_DEF( FT_Error
)
72 pcf_cmap_init( FT_CMap pcfcmap
, /* PCF_CMap */
73 FT_Pointer init_data
)
75 PCF_CMap cmap
= (PCF_CMap
)pcfcmap
;
76 PCF_Face face
= (PCF_Face
)FT_CMAP_FACE( pcfcmap
);
78 FT_UNUSED( init_data
);
81 cmap
->num_encodings
= (FT_UInt
)face
->nencodings
;
82 cmap
->encodings
= face
->encodings
;
88 FT_CALLBACK_DEF( void )
89 pcf_cmap_done( FT_CMap pcfcmap
) /* PCF_CMap */
91 PCF_CMap cmap
= (PCF_CMap
)pcfcmap
;
94 cmap
->encodings
= NULL
;
95 cmap
->num_encodings
= 0;
99 FT_CALLBACK_DEF( FT_UInt
)
100 pcf_cmap_char_index( FT_CMap pcfcmap
, /* PCF_CMap */
103 PCF_CMap cmap
= (PCF_CMap
)pcfcmap
;
104 PCF_Encoding encodings
= cmap
->encodings
;
105 FT_UInt min
, max
, mid
;
110 max
= cmap
->num_encodings
;
117 mid
= ( min
+ max
) >> 1;
118 code
= encodings
[mid
].enc
;
120 if ( charcode
== code
)
122 result
= encodings
[mid
].glyph
+ 1;
126 if ( charcode
< code
)
136 FT_CALLBACK_DEF( FT_UInt
)
137 pcf_cmap_char_next( FT_CMap pcfcmap
, /* PCF_CMap */
138 FT_UInt32
*acharcode
)
140 PCF_CMap cmap
= (PCF_CMap
)pcfcmap
;
141 PCF_Encoding encodings
= cmap
->encodings
;
142 FT_UInt min
, max
, mid
;
143 FT_ULong charcode
= *acharcode
+ 1;
148 max
= cmap
->num_encodings
;
155 mid
= ( min
+ max
) >> 1;
156 code
= encodings
[mid
].enc
;
158 if ( charcode
== code
)
160 result
= encodings
[mid
].glyph
+ 1;
164 if ( charcode
< code
)
171 if ( min
< cmap
->num_encodings
)
173 charcode
= encodings
[min
].enc
;
174 result
= encodings
[min
].glyph
+ 1;
178 if ( charcode
> 0xFFFFFFFFUL
)
180 FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
182 /* XXX: result should be changed to indicate an overflow error */
185 *acharcode
= (FT_UInt32
)charcode
;
190 FT_CALLBACK_TABLE_DEF
191 const FT_CMap_ClassRec pcf_cmap_class
=
193 sizeof ( PCF_CMapRec
),
199 NULL
, NULL
, NULL
, NULL
, NULL
203 FT_CALLBACK_DEF( void )
204 PCF_Face_Done( FT_Face pcfface
) /* PCF_Face */
206 PCF_Face face
= (PCF_Face
)pcfface
;
213 memory
= FT_FACE_MEMORY( face
);
215 FT_FREE( face
->encodings
);
216 FT_FREE( face
->metrics
);
218 /* free properties */
224 if ( face
->properties
)
226 for ( i
= 0; i
< face
->nprops
; i
++ )
228 prop
= &face
->properties
[i
];
231 FT_FREE( prop
->name
);
232 if ( prop
->isString
)
233 FT_FREE( prop
->value
.atom
);
237 FT_FREE( face
->properties
);
240 FT_FREE( face
->toc
.tables
);
241 FT_FREE( pcfface
->family_name
);
242 FT_FREE( pcfface
->style_name
);
243 FT_FREE( pcfface
->available_sizes
);
244 FT_FREE( face
->charset_encoding
);
245 FT_FREE( face
->charset_registry
);
247 FT_TRACE4(( "PCF_Face_Done: done face\n" ));
249 /* close gzip/LZW stream if any */
250 if ( pcfface
->stream
== &face
->gzip_stream
)
252 FT_Stream_Close( &face
->gzip_stream
);
253 pcfface
->stream
= face
->gzip_source
;
258 FT_CALLBACK_DEF( FT_Error
)
259 PCF_Face_Init( FT_Stream stream
,
260 FT_Face pcfface
, /* PCF_Face */
263 FT_Parameter
* params
)
265 PCF_Face face
= (PCF_Face
)pcfface
;
266 FT_Error error
= PCF_Err_Ok
;
268 FT_UNUSED( num_params
);
270 FT_UNUSED( face_index
);
273 error
= pcf_load_font( stream
, face
);
276 PCF_Face_Done( pcfface
);
278 #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \
279 defined( FT_CONFIG_OPTION_USE_LZW )
281 #ifdef FT_CONFIG_OPTION_USE_ZLIB
286 /* this didn't work, try gzip support! */
287 error2
= FT_Stream_OpenGzip( &face
->gzip_stream
, stream
);
288 if ( FT_ERROR_BASE( error2
) == FT_Err_Unimplemented_Feature
)
293 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
295 #ifdef FT_CONFIG_OPTION_USE_LZW
301 /* this didn't work, try LZW support! */
302 error3
= FT_Stream_OpenLZW( &face
->gzip_stream
, stream
);
303 if ( FT_ERROR_BASE( error3
) == FT_Err_Unimplemented_Feature
)
308 #endif /* FT_CONFIG_OPTION_USE_LZW */
313 face
->gzip_source
= stream
;
314 pcfface
->stream
= &face
->gzip_stream
;
316 stream
= pcfface
->stream
;
318 error
= pcf_load_font( stream
, face
);
322 #else /* !(FT_CONFIG_OPTION_USE_ZLIB || FT_CONFIG_OPTION_USE_LZW) */
331 FT_String
*charset_registry
= face
->charset_registry
;
332 FT_String
*charset_encoding
= face
->charset_encoding
;
333 FT_Bool unicode_charmap
= 0;
336 if ( charset_registry
&& charset_encoding
)
338 char* s
= charset_registry
;
341 /* Uh, oh, compare first letters manually to avoid dependency
343 if ( ( s
[0] == 'i' || s
[0] == 'I' ) &&
344 ( s
[1] == 's' || s
[1] == 'S' ) &&
345 ( s
[2] == 'o' || s
[2] == 'O' ) )
348 if ( !ft_strcmp( s
, "10646" ) ||
349 ( !ft_strcmp( s
, "8859" ) &&
350 !ft_strcmp( face
->charset_encoding
, "1" ) ) )
356 FT_CharMapRec charmap
;
359 charmap
.face
= FT_FACE( face
);
360 charmap
.encoding
= FT_ENCODING_NONE
;
361 charmap
.platform_id
= 0;
362 charmap
.encoding_id
= 0;
364 if ( unicode_charmap
)
366 charmap
.encoding
= FT_ENCODING_UNICODE
;
367 charmap
.platform_id
= 3;
368 charmap
.encoding_id
= 1;
371 error
= FT_CMap_New( &pcf_cmap_class
, NULL
, &charmap
, NULL
);
374 /* Select default charmap */
375 if ( pcfface
->num_charmaps
)
376 pcfface
->charmap
= pcfface
->charmaps
[0];
385 FT_TRACE2(( "[not a valid PCF file]\n" ));
386 PCF_Face_Done( pcfface
);
387 error
= PCF_Err_Unknown_File_Format
; /* error */
392 FT_CALLBACK_DEF( FT_Error
)
393 PCF_Size_Select( FT_Size size
,
394 FT_ULong strike_index
)
396 PCF_Accel accel
= &( (PCF_Face
)size
->face
)->accel
;
399 FT_Select_Metrics( size
->face
, strike_index
);
401 size
->metrics
.ascender
= accel
->fontAscent
<< 6;
402 size
->metrics
.descender
= -accel
->fontDescent
<< 6;
403 size
->metrics
.max_advance
= accel
->maxbounds
.characterWidth
<< 6;
409 FT_CALLBACK_DEF( FT_Error
)
410 PCF_Size_Request( FT_Size size
,
411 FT_Size_Request req
)
413 PCF_Face face
= (PCF_Face
)size
->face
;
414 FT_Bitmap_Size
* bsize
= size
->face
->available_sizes
;
415 FT_Error error
= PCF_Err_Invalid_Pixel_Size
;
419 height
= FT_REQUEST_HEIGHT( req
);
420 height
= ( height
+ 32 ) >> 6;
424 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
425 if ( height
== ( ( bsize
->y_ppem
+ 32 ) >> 6 ) )
429 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
430 if ( height
== ( face
->accel
.fontAscent
+
431 face
->accel
.fontDescent
) )
436 error
= PCF_Err_Unimplemented_Feature
;
443 return PCF_Size_Select( size
, 0 );
447 FT_CALLBACK_DEF( FT_Error
)
448 PCF_Glyph_Load( FT_GlyphSlot slot
,
451 FT_Int32 load_flags
)
453 PCF_Face face
= (PCF_Face
)FT_SIZE_FACE( size
);
455 FT_Error error
= PCF_Err_Ok
;
456 FT_Bitmap
* bitmap
= &slot
->bitmap
;
460 FT_UNUSED( load_flags
);
463 FT_TRACE4(( "load_glyph %d ---", glyph_index
));
465 if ( !face
|| glyph_index
>= (FT_UInt
)face
->root
.num_glyphs
)
467 error
= PCF_Err_Invalid_Argument
;
471 stream
= face
->root
.stream
;
473 if ( glyph_index
> 0 )
476 metric
= face
->metrics
+ glyph_index
;
478 bitmap
->rows
= metric
->ascent
+ metric
->descent
;
479 bitmap
->width
= metric
->rightSideBearing
- metric
->leftSideBearing
;
480 bitmap
->num_grays
= 1;
481 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
483 FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
484 PCF_BIT_ORDER( face
->bitmapsFormat
),
485 PCF_BYTE_ORDER( face
->bitmapsFormat
),
486 PCF_GLYPH_PAD( face
->bitmapsFormat
) ));
488 switch ( PCF_GLYPH_PAD( face
->bitmapsFormat
) )
491 bitmap
->pitch
= ( bitmap
->width
+ 7 ) >> 3;
495 bitmap
->pitch
= ( ( bitmap
->width
+ 15 ) >> 4 ) << 1;
499 bitmap
->pitch
= ( ( bitmap
->width
+ 31 ) >> 5 ) << 2;
503 bitmap
->pitch
= ( ( bitmap
->width
+ 63 ) >> 6 ) << 3;
507 return PCF_Err_Invalid_File_Format
;
510 /* XXX: to do: are there cases that need repadding the bitmap? */
511 bytes
= bitmap
->pitch
* bitmap
->rows
;
513 error
= ft_glyphslot_alloc_bitmap( slot
, bytes
);
517 if ( FT_STREAM_SEEK( metric
->bits
) ||
518 FT_STREAM_READ( bitmap
->buffer
, bytes
) )
521 if ( PCF_BIT_ORDER( face
->bitmapsFormat
) != MSBFirst
)
522 BitOrderInvert( bitmap
->buffer
, bytes
);
524 if ( ( PCF_BYTE_ORDER( face
->bitmapsFormat
) !=
525 PCF_BIT_ORDER( face
->bitmapsFormat
) ) )
527 switch ( PCF_SCAN_UNIT( face
->bitmapsFormat
) )
533 TwoByteSwap( bitmap
->buffer
, bytes
);
537 FourByteSwap( bitmap
->buffer
, bytes
);
542 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
543 slot
->bitmap_left
= metric
->leftSideBearing
;
544 slot
->bitmap_top
= metric
->ascent
;
546 slot
->metrics
.horiAdvance
= metric
->characterWidth
<< 6;
547 slot
->metrics
.horiBearingX
= metric
->leftSideBearing
<< 6;
548 slot
->metrics
.horiBearingY
= metric
->ascent
<< 6;
549 slot
->metrics
.width
= ( metric
->rightSideBearing
-
550 metric
->leftSideBearing
) << 6;
551 slot
->metrics
.height
= bitmap
->rows
<< 6;
553 ft_synthesize_vertical_metrics( &slot
->metrics
,
554 ( face
->accel
.fontAscent
+
555 face
->accel
.fontDescent
) << 6 );
557 FT_TRACE4(( " --- ok\n" ));
571 pcf_get_bdf_property( PCF_Face face
,
572 const char* prop_name
,
573 BDF_PropertyRec
*aproperty
)
578 prop
= pcf_find_property( face
, prop_name
);
581 if ( prop
->isString
)
583 aproperty
->type
= BDF_PROPERTY_TYPE_ATOM
;
584 aproperty
->u
.atom
= prop
->value
.atom
;
588 if ( prop
->value
.l
> 0x7FFFFFFFL
|| prop
->value
.l
< ( -1 - 0x7FFFFFFFL
) )
590 FT_TRACE1(( "pcf_get_bdf_property: " ));
591 FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
593 /* Apparently, the PCF driver loads all properties as signed integers!
594 * This really doesn't seem to be a problem, because this is
595 * sufficient for any meaningful values.
597 aproperty
->type
= BDF_PROPERTY_TYPE_INTEGER
;
598 aproperty
->u
.integer
= (FT_Int32
)prop
->value
.l
;
603 return PCF_Err_Invalid_Argument
;
608 pcf_get_charset_id( PCF_Face face
,
609 const char* *acharset_encoding
,
610 const char* *acharset_registry
)
612 *acharset_encoding
= face
->charset_encoding
;
613 *acharset_registry
= face
->charset_registry
;
619 static const FT_Service_BDFRec pcf_service_bdf
=
621 (FT_BDF_GetCharsetIdFunc
)pcf_get_charset_id
,
622 (FT_BDF_GetPropertyFunc
) pcf_get_bdf_property
632 static const FT_ServiceDescRec pcf_services
[] =
634 { FT_SERVICE_ID_BDF
, &pcf_service_bdf
},
635 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_PCF
},
640 FT_CALLBACK_DEF( FT_Module_Interface
)
641 pcf_driver_requester( FT_Module module
,
646 return ft_service_list_lookup( pcf_services
, name
);
650 FT_CALLBACK_TABLE_DEF
651 const FT_Driver_ClassRec pcf_driver_class
=
654 FT_MODULE_FONT_DRIVER
|
655 FT_MODULE_DRIVER_NO_OUTLINES
,
656 sizeof ( FT_DriverRec
),
669 sizeof ( PCF_FaceRec
),
670 sizeof ( FT_SizeRec
),
671 sizeof ( FT_GlyphSlotRec
),
675 0, /* FT_Size_InitFunc */
676 0, /* FT_Size_DoneFunc */
677 0, /* FT_Slot_InitFunc */
678 0, /* FT_Slot_DoneFunc */
680 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
681 ft_stub_set_char_sizes
,
682 ft_stub_set_pixel_sizes
,
686 0, /* FT_Face_GetKerningFunc */
687 0, /* FT_Face_AttachFunc */
688 0, /* FT_Face_GetAdvancesFunc */