3 FreeType font driver for bdf files
5 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 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
29 #include FT_INTERNAL_DEBUG_H
30 #include FT_INTERNAL_STREAM_H
31 #include FT_INTERNAL_OBJECTS_H
34 #include FT_SERVICE_BDF_H
35 #include FT_SERVICE_XFREE86_NAME_H
43 /*************************************************************************/
45 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
46 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
47 /* messages during execution. */
50 #define FT_COMPONENT trace_bdfdriver
53 typedef struct BDF_CMapRec_
56 FT_UInt num_encodings
;
57 BDF_encoding_el
* encodings
;
59 } BDF_CMapRec
, *BDF_CMap
;
62 FT_CALLBACK_DEF( FT_Error
)
63 bdf_cmap_init( FT_CMap bdfcmap
,
64 FT_Pointer init_data
)
66 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
67 BDF_Face face
= (BDF_Face
)FT_CMAP_FACE( cmap
);
68 FT_UNUSED( init_data
);
71 cmap
->num_encodings
= face
->bdffont
->glyphs_used
;
72 cmap
->encodings
= face
->en_table
;
78 FT_CALLBACK_DEF( void )
79 bdf_cmap_done( FT_CMap bdfcmap
)
81 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
84 cmap
->encodings
= NULL
;
85 cmap
->num_encodings
= 0;
89 FT_CALLBACK_DEF( FT_UInt
)
90 bdf_cmap_char_index( FT_CMap bdfcmap
,
93 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
94 BDF_encoding_el
* encodings
= cmap
->encodings
;
95 FT_UInt min
, max
, mid
;
100 max
= cmap
->num_encodings
;
107 mid
= ( min
+ max
) >> 1;
108 code
= encodings
[mid
].enc
;
110 if ( charcode
== code
)
112 /* increase glyph index by 1 -- */
113 /* we reserve slot 0 for the undefined glyph */
114 result
= encodings
[mid
].glyph
+ 1;
118 if ( charcode
< code
)
128 FT_CALLBACK_DEF( FT_UInt
)
129 bdf_cmap_char_next( FT_CMap bdfcmap
,
130 FT_UInt32
*acharcode
)
132 BDF_CMap cmap
= (BDF_CMap
)bdfcmap
;
133 BDF_encoding_el
* encodings
= cmap
->encodings
;
134 FT_UInt min
, max
, mid
;
135 FT_UInt32 charcode
= *acharcode
+ 1;
140 max
= cmap
->num_encodings
;
147 mid
= ( min
+ max
) >> 1;
148 code
= encodings
[mid
].enc
;
150 if ( charcode
== code
)
152 /* increase glyph index by 1 -- */
153 /* we reserve slot 0 for the undefined glyph */
154 result
= encodings
[mid
].glyph
+ 1;
158 if ( charcode
< code
)
165 if ( min
< cmap
->num_encodings
)
167 charcode
= encodings
[min
].enc
;
168 result
= encodings
[min
].glyph
+ 1;
172 *acharcode
= charcode
;
177 FT_CALLBACK_TABLE_DEF
178 const FT_CMap_ClassRec bdf_cmap_class
=
180 sizeof ( BDF_CMapRec
),
189 bdf_interpret_style( BDF_Face bdf
)
191 FT_Error error
= BDF_Err_Ok
;
192 FT_Face face
= FT_FACE( bdf
);
193 FT_Memory memory
= face
->memory
;
194 bdf_font_t
* font
= bdf
->bdffont
;
195 bdf_property_t
* prop
;
198 char* strings
[4] = { NULL
, NULL
, NULL
, NULL
};
202 face
->style_flags
= 0;
204 prop
= bdf_get_font_property( font
, (char *)"SLANT" );
205 if ( prop
&& prop
->format
== BDF_ATOM
&&
207 ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' ||
208 *(prop
->value
.atom
) == 'I' || *(prop
->value
.atom
) == 'i' ) )
210 face
->style_flags
|= FT_STYLE_FLAG_ITALIC
;
211 strings
[2] = ( *(prop
->value
.atom
) == 'O' || *(prop
->value
.atom
) == 'o' )
216 prop
= bdf_get_font_property( font
, (char *)"WEIGHT_NAME" );
217 if ( prop
&& prop
->format
== BDF_ATOM
&&
219 ( *(prop
->value
.atom
) == 'B' || *(prop
->value
.atom
) == 'b' ) )
221 face
->style_flags
|= FT_STYLE_FLAG_BOLD
;
222 strings
[1] = (char *)"Bold";
225 prop
= bdf_get_font_property( font
, (char *)"SETWIDTH_NAME" );
226 if ( prop
&& prop
->format
== BDF_ATOM
&&
227 prop
->value
.atom
&& *(prop
->value
.atom
) &&
228 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
229 strings
[3] = (char *)(prop
->value
.atom
);
231 prop
= bdf_get_font_property( font
, (char *)"ADD_STYLE_NAME" );
232 if ( prop
&& prop
->format
== BDF_ATOM
&&
233 prop
->value
.atom
&& *(prop
->value
.atom
) &&
234 !( *(prop
->value
.atom
) == 'N' || *(prop
->value
.atom
) == 'n' ) )
235 strings
[0] = (char *)(prop
->value
.atom
);
239 for ( len
= 0, nn
= 0; nn
< 4; nn
++ )
244 lengths
[nn
] = ft_strlen( strings
[nn
] );
245 len
+= lengths
[nn
] + 1;
251 strings
[0] = (char *)"Regular";
252 lengths
[0] = ft_strlen( strings
[0] );
253 len
= lengths
[0] + 1;
260 if ( FT_ALLOC( face
->style_name
, len
) )
263 s
= face
->style_name
;
265 for ( nn
= 0; nn
< 4; nn
++ )
267 char* src
= strings
[nn
];
275 /* separate elements with a space */
276 if ( s
!= face
->style_name
)
279 ft_memcpy( s
, src
, len
);
281 /* need to convert spaces to dashes for */
282 /* add_style_name and setwidth_name */
283 if ( nn
== 0 || nn
== 3 )
288 for ( mm
= 0; mm
< len
; mm
++ )
302 FT_CALLBACK_DEF( void )
303 BDF_Face_Done( FT_Face bdfface
) /* BDF_Face */
305 BDF_Face face
= (BDF_Face
)bdfface
;
306 FT_Memory memory
= FT_FACE_MEMORY( face
);
309 bdf_free_font( face
->bdffont
);
311 FT_FREE( face
->en_table
);
313 FT_FREE( face
->charset_encoding
);
314 FT_FREE( face
->charset_registry
);
315 FT_FREE( bdfface
->family_name
);
316 FT_FREE( bdfface
->style_name
);
318 FT_FREE( bdfface
->available_sizes
);
320 FT_FREE( face
->bdffont
);
322 FT_TRACE4(( "BDF_Face_Done: done face\n" ));
326 FT_CALLBACK_DEF( FT_Error
)
327 BDF_Face_Init( FT_Stream stream
,
328 FT_Face bdfface
, /* BDF_Face */
331 FT_Parameter
* params
)
333 FT_Error error
= BDF_Err_Ok
;
334 BDF_Face face
= (BDF_Face
)bdfface
;
335 FT_Memory memory
= FT_FACE_MEMORY( face
);
337 bdf_font_t
* font
= NULL
;
338 bdf_options_t options
;
340 FT_UNUSED( num_params
);
342 FT_UNUSED( face_index
);
345 if ( FT_STREAM_SEEK( 0 ) )
348 options
.correct_metrics
= 1; /* FZ XXX: options semantics */
349 options
.keep_unencoded
= 1;
350 options
.keep_comments
= 0;
351 options
.font_spacing
= BDF_PROPORTIONAL
;
353 error
= bdf_load_font( stream
, memory
, &options
, &font
);
354 if ( error
== BDF_Err_Missing_Startfont_Field
)
356 FT_TRACE2(( "[not a valid BDF file]\n" ));
362 /* we have a bdf font: let's construct the face object */
363 face
->bdffont
= font
;
365 bdf_property_t
* prop
= NULL
;
368 FT_TRACE4(( "number of glyphs: %d (%d)\n",
370 font
->glyphs_used
));
371 FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",
372 font
->unencoded_size
,
373 font
->unencoded_used
));
375 bdfface
->num_faces
= 1;
376 bdfface
->face_index
= 0;
377 bdfface
->face_flags
= FT_FACE_FLAG_FIXED_SIZES
|
378 FT_FACE_FLAG_HORIZONTAL
|
379 FT_FACE_FLAG_FAST_GLYPHS
;
381 prop
= bdf_get_font_property( font
, "SPACING" );
382 if ( prop
&& prop
->format
== BDF_ATOM
&&
384 ( *(prop
->value
.atom
) == 'M' || *(prop
->value
.atom
) == 'm' ||
385 *(prop
->value
.atom
) == 'C' || *(prop
->value
.atom
) == 'c' ) )
386 bdfface
->face_flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
388 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
389 /* FZ XXX: I need a font to implement this */
391 prop
= bdf_get_font_property( font
, "FAMILY_NAME" );
392 if ( prop
&& prop
->value
.atom
)
394 if ( FT_STRDUP( bdfface
->family_name
, prop
->value
.atom
) )
398 bdfface
->family_name
= 0;
400 if ( ( error
= bdf_interpret_style( face
) ) != 0 )
403 /* the number of glyphs (with one slot for the undefined glyph */
404 /* at position 0 and all unencoded glyphs) */
405 bdfface
->num_glyphs
= font
->glyphs_size
+ 1;
407 bdfface
->num_fixed_sizes
= 1;
408 if ( FT_NEW_ARRAY( bdfface
->available_sizes
, 1 ) )
412 FT_Bitmap_Size
* bsize
= bdfface
->available_sizes
;
413 FT_Short resolution_x
= 0, resolution_y
= 0;
416 FT_MEM_ZERO( bsize
, sizeof ( FT_Bitmap_Size
) );
418 bsize
->height
= (FT_Short
)( font
->font_ascent
+ font
->font_descent
);
420 prop
= bdf_get_font_property( font
, "AVERAGE_WIDTH" );
422 bsize
->width
= (FT_Short
)( ( prop
->value
.int32
+ 5 ) / 10 );
424 bsize
->width
= (FT_Short
)( bsize
->height
* 2/3 );
426 prop
= bdf_get_font_property( font
, "POINT_SIZE" );
428 /* convert from 722.7 decipoints to 72 points per inch */
430 (FT_Pos
)( ( prop
->value
.int32
* 64 * 7200 + 36135L ) / 72270L );
432 bsize
->size
= bsize
->width
<< 6;
434 prop
= bdf_get_font_property( font
, "PIXEL_SIZE" );
436 bsize
->y_ppem
= (FT_Short
)prop
->value
.int32
<< 6;
438 prop
= bdf_get_font_property( font
, "RESOLUTION_X" );
440 resolution_x
= (FT_Short
)prop
->value
.int32
;
442 prop
= bdf_get_font_property( font
, "RESOLUTION_Y" );
444 resolution_y
= (FT_Short
)prop
->value
.int32
;
446 if ( bsize
->y_ppem
== 0 )
448 bsize
->y_ppem
= bsize
->size
;
450 bsize
->y_ppem
= bsize
->y_ppem
* resolution_y
/ 72;
452 if ( resolution_x
&& resolution_y
)
453 bsize
->x_ppem
= bsize
->y_ppem
* resolution_x
/ resolution_y
;
455 bsize
->x_ppem
= bsize
->y_ppem
;
460 bdf_glyph_t
* cur
= font
->glyphs
;
464 if ( FT_NEW_ARRAY( face
->en_table
, font
->glyphs_size
) )
467 face
->default_glyph
= 0;
468 for ( n
= 0; n
< font
->glyphs_size
; n
++ )
470 (face
->en_table
[n
]).enc
= cur
[n
].encoding
;
471 FT_TRACE4(( "idx %d, val 0x%lX\n", n
, cur
[n
].encoding
));
472 (face
->en_table
[n
]).glyph
= (FT_Short
)n
;
474 if ( cur
[n
].encoding
== font
->default_char
)
475 face
->default_glyph
= n
;
481 bdf_property_t
*charset_registry
= 0, *charset_encoding
= 0;
482 FT_Bool unicode_charmap
= 0;
486 bdf_get_font_property( font
, "CHARSET_REGISTRY" );
488 bdf_get_font_property( font
, "CHARSET_ENCODING" );
489 if ( charset_registry
&& charset_encoding
)
491 if ( charset_registry
->format
== BDF_ATOM
&&
492 charset_encoding
->format
== BDF_ATOM
&&
493 charset_registry
->value
.atom
&&
494 charset_encoding
->value
.atom
)
499 if ( FT_STRDUP( face
->charset_encoding
,
500 charset_encoding
->value
.atom
) ||
501 FT_STRDUP( face
->charset_registry
,
502 charset_registry
->value
.atom
) )
505 /* Uh, oh, compare first letters manually to avoid dependency */
507 s
= face
->charset_registry
;
508 if ( ( s
[0] == 'i' || s
[0] == 'I' ) &&
509 ( s
[1] == 's' || s
[1] == 'S' ) &&
510 ( s
[2] == 'o' || s
[2] == 'O' ) )
513 if ( !ft_strcmp( s
, "10646" ) ||
514 ( !ft_strcmp( s
, "8859" ) &&
515 !ft_strcmp( face
->charset_encoding
, "1" ) ) )
520 FT_CharMapRec charmap
;
523 charmap
.face
= FT_FACE( face
);
524 charmap
.encoding
= FT_ENCODING_NONE
;
525 charmap
.platform_id
= 0;
526 charmap
.encoding_id
= 0;
528 if ( unicode_charmap
)
530 charmap
.encoding
= FT_ENCODING_UNICODE
;
531 charmap
.platform_id
= 3;
532 charmap
.encoding_id
= 1;
535 error
= FT_CMap_New( &bdf_cmap_class
, NULL
, &charmap
, NULL
);
538 /* Select default charmap */
539 if ( bdfface
->num_charmaps
)
540 bdfface
->charmap
= bdfface
->charmaps
[0];
548 /* otherwise assume Adobe standard encoding */
551 FT_CharMapRec charmap
;
554 charmap
.face
= FT_FACE( face
);
555 charmap
.encoding
= FT_ENCODING_ADOBE_STANDARD
;
556 charmap
.platform_id
= 7;
557 charmap
.encoding_id
= 0;
559 error
= FT_CMap_New( &bdf_cmap_class
, NULL
, &charmap
, NULL
);
561 /* Select default charmap */
562 if ( bdfface
->num_charmaps
)
563 bdfface
->charmap
= bdfface
->charmaps
[0];
572 BDF_Face_Done( bdfface
);
573 return BDF_Err_Unknown_File_Format
;
577 FT_CALLBACK_DEF( FT_Error
)
578 BDF_Size_Select( FT_Size size
,
579 FT_ULong strike_index
)
581 bdf_font_t
* bdffont
= ( (BDF_Face
)size
->face
)->bdffont
;
584 FT_Select_Metrics( size
->face
, strike_index
);
586 size
->metrics
.ascender
= bdffont
->font_ascent
<< 6;
587 size
->metrics
.descender
= -bdffont
->font_descent
<< 6;
588 size
->metrics
.max_advance
= bdffont
->bbx
.width
<< 6;
594 FT_CALLBACK_DEF( FT_Error
)
595 BDF_Size_Request( FT_Size size
,
596 FT_Size_Request req
)
598 FT_Face face
= size
->face
;
599 FT_Bitmap_Size
* bsize
= face
->available_sizes
;
600 bdf_font_t
* bdffont
= ( (BDF_Face
)face
)->bdffont
;
601 FT_Error error
= BDF_Err_Invalid_Pixel_Size
;
605 height
= FT_REQUEST_HEIGHT( req
);
606 height
= ( height
+ 32 ) >> 6;
610 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
611 if ( height
== ( bsize
->y_ppem
+ 32 ) >> 6 )
615 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
616 if ( height
== ( bdffont
->font_ascent
+
617 bdffont
->font_descent
) )
622 error
= BDF_Err_Unimplemented_Feature
;
629 return BDF_Size_Select( size
, 0 );
634 FT_CALLBACK_DEF( FT_Error
)
635 BDF_Glyph_Load( FT_GlyphSlot slot
,
638 FT_Int32 load_flags
)
640 BDF_Face bdf
= (BDF_Face
)FT_SIZE_FACE( size
);
641 FT_Face face
= FT_FACE( bdf
);
642 FT_Error error
= BDF_Err_Ok
;
643 FT_Bitmap
* bitmap
= &slot
->bitmap
;
645 int bpp
= bdf
->bdffont
->bpp
;
647 FT_UNUSED( load_flags
);
650 if ( !face
|| glyph_index
>= (FT_UInt
)face
->num_glyphs
)
652 error
= BDF_Err_Invalid_Argument
;
656 /* index 0 is the undefined glyph */
657 if ( glyph_index
== 0 )
658 glyph_index
= bdf
->default_glyph
;
662 /* slot, bitmap => freetype, glyph => bdflib */
663 glyph
= bdf
->bdffont
->glyphs
[glyph_index
];
665 bitmap
->rows
= glyph
.bbx
.height
;
666 bitmap
->width
= glyph
.bbx
.width
;
667 bitmap
->pitch
= glyph
.bpr
;
669 /* note: we don't allocate a new array to hold the bitmap; */
670 /* we can simply point to it */
671 ft_glyphslot_set_bitmap( slot
, glyph
.bitmap
);
676 bitmap
->pixel_mode
= FT_PIXEL_MODE_MONO
;
679 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY2
;
682 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY4
;
685 bitmap
->pixel_mode
= FT_PIXEL_MODE_GRAY
;
686 bitmap
->num_grays
= 256;
690 slot
->format
= FT_GLYPH_FORMAT_BITMAP
;
691 slot
->bitmap_left
= glyph
.bbx
.x_offset
;
692 slot
->bitmap_top
= glyph
.bbx
.ascent
;
694 slot
->metrics
.horiAdvance
= glyph
.dwidth
<< 6;
695 slot
->metrics
.horiBearingX
= glyph
.bbx
.x_offset
<< 6;
696 slot
->metrics
.horiBearingY
= glyph
.bbx
.ascent
<< 6;
697 slot
->metrics
.width
= bitmap
->width
<< 6;
698 slot
->metrics
.height
= bitmap
->rows
<< 6;
701 * XXX DWIDTH1 and VVECTOR should be parsed and
702 * used here, provided such fonts do exist.
704 ft_synthesize_vertical_metrics( &slot
->metrics
,
705 bdf
->bdffont
->bbx
.height
<< 6 );
719 bdf_get_bdf_property( BDF_Face face
,
720 const char* prop_name
,
721 BDF_PropertyRec
*aproperty
)
723 bdf_property_t
* prop
;
726 FT_ASSERT( face
&& face
->bdffont
);
728 prop
= bdf_get_font_property( face
->bdffont
, prop_name
);
731 switch ( prop
->format
)
734 aproperty
->type
= BDF_PROPERTY_TYPE_ATOM
;
735 aproperty
->u
.atom
= prop
->value
.atom
;
739 aproperty
->type
= BDF_PROPERTY_TYPE_INTEGER
;
740 aproperty
->u
.integer
= prop
->value
.int32
;
744 aproperty
->type
= BDF_PROPERTY_TYPE_CARDINAL
;
745 aproperty
->u
.cardinal
= prop
->value
.card32
;
755 return BDF_Err_Invalid_Argument
;
760 bdf_get_charset_id( BDF_Face face
,
761 const char* *acharset_encoding
,
762 const char* *acharset_registry
)
764 *acharset_encoding
= face
->charset_encoding
;
765 *acharset_registry
= face
->charset_registry
;
771 static const FT_Service_BDFRec bdf_service_bdf
=
773 (FT_BDF_GetCharsetIdFunc
)bdf_get_charset_id
,
774 (FT_BDF_GetPropertyFunc
) bdf_get_bdf_property
784 static const FT_ServiceDescRec bdf_services
[] =
786 { FT_SERVICE_ID_BDF
, &bdf_service_bdf
},
787 { FT_SERVICE_ID_XF86_NAME
, FT_XF86_FORMAT_BDF
},
792 FT_CALLBACK_DEF( FT_Module_Interface
)
793 bdf_driver_requester( FT_Module module
,
798 return ft_service_list_lookup( bdf_services
, name
);
803 FT_CALLBACK_TABLE_DEF
804 const FT_Driver_ClassRec bdf_driver_class
=
807 FT_MODULE_FONT_DRIVER
|
808 FT_MODULE_DRIVER_NO_OUTLINES
,
809 sizeof ( FT_DriverRec
),
817 (FT_Module_Constructor
)0,
818 (FT_Module_Destructor
) 0,
819 (FT_Module_Requester
) bdf_driver_requester
822 sizeof ( BDF_FaceRec
),
823 sizeof ( FT_SizeRec
),
824 sizeof ( FT_GlyphSlotRec
),
828 0, /* FT_Size_InitFunc */
829 0, /* FT_Size_DoneFunc */
830 0, /* FT_Slot_InitFunc */
831 0, /* FT_Slot_DoneFunc */
833 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
834 ft_stub_set_char_sizes
,
835 ft_stub_set_pixel_sizes
,
839 0, /* FT_Face_GetKerningFunc */
840 0, /* FT_Face_AttachFunc */
841 0, /* FT_Face_GetAdvancesFunc */