3 FreeType font driver for pcf files
5 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006 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_UInt32 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 *acharcode
= charcode
;
183 FT_CALLBACK_TABLE_DEF
184 const FT_CMap_ClassRec pcf_cmap_class
=
186 sizeof ( PCF_CMapRec
),
194 FT_CALLBACK_DEF( void )
195 PCF_Face_Done( FT_Face pcfface
) /* PCF_Face */
197 PCF_Face face
= (PCF_Face
)pcfface
;
198 FT_Memory memory
= FT_FACE_MEMORY( face
);
201 FT_FREE( face
->encodings
);
202 FT_FREE( face
->metrics
);
204 /* free properties */
210 if ( face
->properties
)
212 for ( i
= 0; i
< face
->nprops
; i
++ )
214 prop
= &face
->properties
[i
];
217 FT_FREE( prop
->name
);
218 if ( prop
->isString
)
219 FT_FREE( prop
->value
.atom
);
223 FT_FREE( face
->properties
);
226 FT_FREE( face
->toc
.tables
);
227 FT_FREE( pcfface
->family_name
);
228 FT_FREE( pcfface
->style_name
);
229 FT_FREE( pcfface
->available_sizes
);
230 FT_FREE( face
->charset_encoding
);
231 FT_FREE( face
->charset_registry
);
233 FT_TRACE4(( "PCF_Face_Done: done face\n" ));
235 /* close gzip/LZW stream if any */
236 if ( pcfface
->stream
== &face
->gzip_stream
)
238 FT_Stream_Close( &face
->gzip_stream
);
239 pcfface
->stream
= face
->gzip_source
;
244 FT_CALLBACK_DEF( FT_Error
)
245 PCF_Face_Init( FT_Stream stream
,
246 FT_Face pcfface
, /* PCF_Face */
249 FT_Parameter
* params
)
251 PCF_Face face
= (PCF_Face
)pcfface
;
252 FT_Error error
= PCF_Err_Ok
;
254 FT_UNUSED( num_params
);
256 FT_UNUSED( face_index
);
259 error
= pcf_load_font( stream
, face
);
265 PCF_Face_Done( pcfface
);
267 /* this didn't work, try gzip support! */
268 error2
= FT_Stream_OpenGzip( &face
->gzip_stream
, stream
);
269 if ( FT_ERROR_BASE( error2
) == FT_Err_Unimplemented_Feature
)
278 /* this didn't work, try LZW support! */
279 error3
= FT_Stream_OpenLZW( &face
->gzip_stream
, stream
);
280 if ( FT_ERROR_BASE( error3
) == FT_Err_Unimplemented_Feature
)
287 face
->gzip_source
= stream
;
288 pcfface
->stream
= &face
->gzip_stream
;
290 stream
= pcfface
->stream
;
292 error
= pcf_load_font( stream
, face
);
298 face
->gzip_source
= stream
;
299 pcfface
->stream
= &face
->gzip_stream
;
301 stream
= pcfface
->stream
;
303 error
= pcf_load_font( stream
, face
);
311 FT_String
*charset_registry
= face
->charset_registry
;
312 FT_String
*charset_encoding
= face
->charset_encoding
;
313 FT_Bool unicode_charmap
= 0;
316 if ( charset_registry
&& charset_encoding
)
318 char* s
= charset_registry
;
321 /* Uh, oh, compare first letters manually to avoid dependency
323 if ( ( s
[0] == 'i' || s
[0] == 'I' ) &&
324 ( s
[1] == 's' || s
[1] == 'S' ) &&
325 ( s
[2] == 'o' || s
[2] == 'O' ) )
328 if ( !ft_strcmp( s
, "10646" ) ||
329 ( !ft_strcmp( s
, "8859" ) &&
330 !ft_strcmp( face
->charset_encoding
, "1" ) ) )
336 FT_CharMapRec charmap
;
339 charmap
.face
= FT_FACE( face
);
340 charmap
.encoding
= FT_ENCODING_NONE
;
341 charmap
.platform_id
= 0;
342 charmap
.encoding_id
= 0;
344 if ( unicode_charmap
)
346 charmap
.encoding
= FT_ENCODING_UNICODE
;
347 charmap
.platform_id
= 3;
348 charmap
.encoding_id
= 1;
351 error
= FT_CMap_New( &pcf_cmap_class
, NULL
, &charmap
, NULL
);
354 /* Select default charmap */
355 if ( pcfface
->num_charmaps
)
356 pcfface
->charmap
= pcfface
->charmaps
[0];
365 FT_TRACE2(( "[not a valid PCF file]\n" ));
366 PCF_Face_Done( pcfface
);
367 error
= PCF_Err_Unknown_File_Format
; /* error */
372 FT_CALLBACK_DEF( FT_Error
)
373 PCF_Size_Select( FT_Size size
,
374 FT_ULong strike_index
)
376 PCF_Accel accel
= &( (PCF_Face
)size
->face
)->accel
;
379 FT_Select_Metrics( size
->face
, strike_index
);
381 size
->metrics
.ascender
= accel
->fontAscent
<< 6;
382 size
->metrics
.descender
= -accel
->fontDescent
<< 6;
383 size
->metrics
.max_advance
= accel
->maxbounds
.characterWidth
<< 6;
389 FT_CALLBACK_DEF( FT_Error
)
390 PCF_Size_Request( FT_Size size
,
391 FT_Size_Request req
)
393 PCF_Face face
= (PCF_Face
)size
->face
;
394 FT_Bitmap_Size
* bsize
= size
->face
->available_sizes
;
395 FT_Error error
= PCF_Err_Invalid_Pixel_Size
;
399 height
= FT_REQUEST_HEIGHT( req
);
400 height
= ( height
+ 32 ) >> 6;
404 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
405 if ( height
== ( bsize
->y_ppem
+ 32 ) >> 6 )
409 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
410 if ( height
== ( face
->accel
.fontAscent
+
411 face
->accel
.fontDescent
) )
416 error
= PCF_Err_Unimplemented_Feature
;
423 return PCF_Size_Select( size
, 0 );
427 FT_CALLBACK_DEF( FT_Error
)
428 PCF_Glyph_Load( FT_GlyphSlot slot
,
431 FT_Int32 load_flags
)
433 PCF_Face face
= (PCF_Face
)FT_SIZE_FACE( size
);
434 FT_Stream stream
= face
->root
.stream
;
435 FT_Error error
= PCF_Err_Ok
;
436 FT_Bitmap
* bitmap
= &slot
->bitmap
;
440 FT_UNUSED( load_flags
);
443 FT_TRACE4(( "load_glyph %d ---", glyph_index
));
445 if ( !face
|| glyph_index
>= (FT_UInt
)face
->root
.num_glyphs
)
447 error
= PCF_Err_Invalid_Argument
;
451 if ( glyph_index
> 0 )
454 metric
= face
->metrics
+ glyph_index
;
456 bitmap
->rows
= metric
->ascent
+ metric
->descent
;
457 bitmap
->width
= metric
->rightSideBearing
- metric
->leftSideBearing
;
458 bitmap
->num_grays
= 1;
459 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
461 FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
462 PCF_BIT_ORDER( face
->bitmapsFormat
),
463 PCF_BYTE_ORDER( face
->bitmapsFormat
),
464 PCF_GLYPH_PAD( face
->bitmapsFormat
) ));
466 switch ( PCF_GLYPH_PAD( face
->bitmapsFormat
) )
469 bitmap
->pitch
= ( bitmap
->width
+ 7 ) >> 3;
473 bitmap
->pitch
= ( ( bitmap
->width
+ 15 ) >> 4 ) << 1;
477 bitmap
->pitch
= ( ( bitmap
->width
+ 31 ) >> 5 ) << 2;
481 bitmap
->pitch
= ( ( bitmap
->width
+ 63 ) >> 6 ) << 3;
485 return PCF_Err_Invalid_File_Format
;
488 /* XXX: to do: are there cases that need repadding the bitmap? */
489 bytes
= bitmap
->pitch
* bitmap
->rows
;
491 error
= ft_glyphslot_alloc_bitmap( slot
, bytes
);
495 if ( FT_STREAM_SEEK( metric
->bits
) ||
496 FT_STREAM_READ( bitmap
->buffer
, bytes
) )
499 if ( PCF_BIT_ORDER( face
->bitmapsFormat
) != MSBFirst
)
500 BitOrderInvert( bitmap
->buffer
, bytes
);
502 if ( ( PCF_BYTE_ORDER( face
->bitmapsFormat
) !=
503 PCF_BIT_ORDER( face
->bitmapsFormat
) ) )
505 switch ( PCF_SCAN_UNIT( face
->bitmapsFormat
) )
511 TwoByteSwap( bitmap
->buffer
, bytes
);
515 FourByteSwap( bitmap
->buffer
, bytes
);
520 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
521 slot
->bitmap_left
= metric
->leftSideBearing
;
522 slot
->bitmap_top
= metric
->ascent
;
524 slot
->metrics
.horiAdvance
= metric
->characterWidth
<< 6;
525 slot
->metrics
.horiBearingX
= metric
->leftSideBearing
<< 6;
526 slot
->metrics
.horiBearingY
= metric
->ascent
<< 6;
527 slot
->metrics
.width
= ( metric
->rightSideBearing
-
528 metric
->leftSideBearing
) << 6;
529 slot
->metrics
.height
= bitmap
->rows
<< 6;
531 ft_synthesize_vertical_metrics( &slot
->metrics
,
532 ( face
->accel
.fontAscent
+
533 face
->accel
.fontDescent
) << 6 );
535 FT_TRACE4(( " --- ok\n" ));
549 pcf_get_bdf_property( PCF_Face face
,
550 const char* prop_name
,
551 BDF_PropertyRec
*aproperty
)
556 prop
= pcf_find_property( face
, prop_name
);
559 if ( prop
->isString
)
561 aproperty
->type
= BDF_PROPERTY_TYPE_ATOM
;
562 aproperty
->u
.atom
= prop
->value
.atom
;
566 /* Apparently, the PCF driver loads all properties as signed integers!
567 * This really doesn't seem to be a problem, because this is
568 * sufficient for any meaningful values.
570 aproperty
->type
= BDF_PROPERTY_TYPE_INTEGER
;
571 aproperty
->u
.integer
= prop
->value
.integer
;
576 return PCF_Err_Invalid_Argument
;
581 pcf_get_charset_id( PCF_Face face
,
582 const char* *acharset_encoding
,
583 const char* *acharset_registry
)
585 *acharset_encoding
= face
->charset_encoding
;
586 *acharset_registry
= face
->charset_registry
;
592 static const FT_Service_BDFRec pcf_service_bdf
=
594 (FT_BDF_GetCharsetIdFunc
)pcf_get_charset_id
,
595 (FT_BDF_GetPropertyFunc
) pcf_get_bdf_property
605 static const FT_ServiceDescRec pcf_services
[] =
607 { FT_SERVICE_ID_BDF
, &pcf_service_bdf
},
608 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_PCF
},
613 FT_CALLBACK_DEF( FT_Module_Interface
)
614 pcf_driver_requester( FT_Module module
,
619 return ft_service_list_lookup( pcf_services
, name
);
623 FT_CALLBACK_TABLE_DEF
624 const FT_Driver_ClassRec pcf_driver_class
=
627 FT_MODULE_FONT_DRIVER
|
628 FT_MODULE_DRIVER_NO_OUTLINES
,
629 sizeof ( FT_DriverRec
),
642 sizeof ( PCF_FaceRec
),
643 sizeof ( FT_SizeRec
),
644 sizeof ( FT_GlyphSlotRec
),
648 0, /* FT_Size_InitFunc */
649 0, /* FT_Size_DoneFunc */
650 0, /* FT_Slot_InitFunc */
651 0, /* FT_Slot_DoneFunc */
653 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
654 ft_stub_set_char_sizes
,
655 ft_stub_set_pixel_sizes
,
659 0, /* FT_Face_GetKerningFunc */
660 0, /* FT_Face_AttachFunc */
661 0, /* FT_Face_GetAdvancesFunc */