3
FreeType font driver for bdf files
5
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 ),
186
NULL, NULL, NULL, NULL, NULL
191
bdf_interpret_style( BDF_Face bdf )
193
FT_Error error = BDF_Err_Ok;
194
FT_Face face = FT_FACE( bdf );
195
FT_Memory memory = face->memory;
196
bdf_font_t* font = bdf->bdffont;
197
bdf_property_t* prop;
200
char* strings[4] = { NULL, NULL, NULL, NULL };
204
face->style_flags = 0;
206
prop = bdf_get_font_property( font, (char *)"SLANT" );
207
if ( prop && prop->format == BDF_ATOM &&
209
( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
210
*(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
212
face->style_flags |= FT_STYLE_FLAG_ITALIC;
213
strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
218
prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );
219
if ( prop && prop->format == BDF_ATOM &&
221
( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
223
face->style_flags |= FT_STYLE_FLAG_BOLD;
224
strings[1] = (char *)"Bold";
227
prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" );
228
if ( prop && prop->format == BDF_ATOM &&
229
prop->value.atom && *(prop->value.atom) &&
230
!( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
231
strings[3] = (char *)(prop->value.atom);
233
prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" );
234
if ( prop && prop->format == BDF_ATOM &&
235
prop->value.atom && *(prop->value.atom) &&
236
!( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
237
strings[0] = (char *)(prop->value.atom);
241
for ( len = 0, nn = 0; nn < 4; nn++ )
246
lengths[nn] = ft_strlen( strings[nn] );
247
len += lengths[nn] + 1;
253
strings[0] = (char *)"Regular";
254
lengths[0] = ft_strlen( strings[0] );
255
len = lengths[0] + 1;
262
if ( FT_ALLOC( face->style_name, len ) )
265
s = face->style_name;
267
for ( nn = 0; nn < 4; nn++ )
269
char* src = strings[nn];
277
/* separate elements with a space */
278
if ( s != face->style_name )
281
ft_memcpy( s, src, len );
283
/* need to convert spaces to dashes for */
284
/* add_style_name and setwidth_name */
285
if ( nn == 0 || nn == 3 )
290
for ( mm = 0; mm < len; mm++ )
304
FT_CALLBACK_DEF( void )
305
BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */
307
BDF_Face face = (BDF_Face)bdfface;
314
memory = FT_FACE_MEMORY( face );
316
bdf_free_font( face->bdffont );
318
FT_FREE( face->en_table );
320
FT_FREE( face->charset_encoding );
321
FT_FREE( face->charset_registry );
322
FT_FREE( bdfface->family_name );
323
FT_FREE( bdfface->style_name );
325
FT_FREE( bdfface->available_sizes );
327
FT_FREE( face->bdffont );
329
FT_TRACE4(( "BDF_Face_Done: done face\n" ));
333
FT_CALLBACK_DEF( FT_Error )
334
BDF_Face_Init( FT_Stream stream,
335
FT_Face bdfface, /* BDF_Face */
338
FT_Parameter* params )
340
FT_Error error = BDF_Err_Ok;
341
BDF_Face face = (BDF_Face)bdfface;
342
FT_Memory memory = FT_FACE_MEMORY( face );
344
bdf_font_t* font = NULL;
345
bdf_options_t options;
347
FT_UNUSED( num_params );
349
FT_UNUSED( face_index );
352
if ( FT_STREAM_SEEK( 0 ) )
355
options.correct_metrics = 1; /* FZ XXX: options semantics */
356
options.keep_unencoded = 1;
357
options.keep_comments = 0;
358
options.font_spacing = BDF_PROPORTIONAL;
360
error = bdf_load_font( stream, memory, &options, &font );
361
if ( error == BDF_Err_Missing_Startfont_Field )
363
FT_TRACE2(( "[not a valid BDF file]\n" ));
369
/* we have a bdf font: let's construct the face object */
370
face->bdffont = font;
372
bdf_property_t* prop = NULL;
375
FT_TRACE4(( "number of glyphs: %d (%d)\n",
377
font->glyphs_used ));
378
FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",
379
font->unencoded_size,
380
font->unencoded_used ));
382
bdfface->num_faces = 1;
383
bdfface->face_index = 0;
384
bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES |
385
FT_FACE_FLAG_HORIZONTAL |
386
FT_FACE_FLAG_FAST_GLYPHS;
388
prop = bdf_get_font_property( font, "SPACING" );
389
if ( prop && prop->format == BDF_ATOM &&
391
( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
392
*(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
393
bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
395
/* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
396
/* FZ XXX: I need a font to implement this */
398
prop = bdf_get_font_property( font, "FAMILY_NAME" );
399
if ( prop && prop->value.atom )
401
if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
405
bdfface->family_name = 0;
407
if ( ( error = bdf_interpret_style( face ) ) != 0 )
410
/* the number of glyphs (with one slot for the undefined glyph */
411
/* at position 0 and all unencoded glyphs) */
412
bdfface->num_glyphs = font->glyphs_size + 1;
414
bdfface->num_fixed_sizes = 1;
415
if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
419
FT_Bitmap_Size* bsize = bdfface->available_sizes;
420
FT_Short resolution_x = 0, resolution_y = 0;
423
FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
425
bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
427
prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
429
bsize->width = (FT_Short)( ( prop->value.int32 + 5 ) / 10 );
431
bsize->width = (FT_Short)( bsize->height * 2/3 );
433
prop = bdf_get_font_property( font, "POINT_SIZE" );
435
/* convert from 722.7 decipoints to 72 points per inch */
437
(FT_Pos)( ( prop->value.int32 * 64 * 7200 + 36135L ) / 72270L );
439
bsize->size = bsize->width << 6;
441
prop = bdf_get_font_property( font, "PIXEL_SIZE" );
443
bsize->y_ppem = (FT_Short)prop->value.int32 << 6;
445
prop = bdf_get_font_property( font, "RESOLUTION_X" );
447
resolution_x = (FT_Short)prop->value.int32;
449
prop = bdf_get_font_property( font, "RESOLUTION_Y" );
451
resolution_y = (FT_Short)prop->value.int32;
453
if ( bsize->y_ppem == 0 )
455
bsize->y_ppem = bsize->size;
457
bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
459
if ( resolution_x && resolution_y )
460
bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
462
bsize->x_ppem = bsize->y_ppem;
467
bdf_glyph_t* cur = font->glyphs;
471
if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
474
face->default_glyph = 0;
475
for ( n = 0; n < font->glyphs_size; n++ )
477
(face->en_table[n]).enc = cur[n].encoding;
478
FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding ));
479
(face->en_table[n]).glyph = (FT_Short)n;
481
if ( cur[n].encoding == font->default_char )
482
face->default_glyph = n;
488
bdf_property_t *charset_registry = 0, *charset_encoding = 0;
489
FT_Bool unicode_charmap = 0;
493
bdf_get_font_property( font, "CHARSET_REGISTRY" );
495
bdf_get_font_property( font, "CHARSET_ENCODING" );
496
if ( charset_registry && charset_encoding )
498
if ( charset_registry->format == BDF_ATOM &&
499
charset_encoding->format == BDF_ATOM &&
500
charset_registry->value.atom &&
501
charset_encoding->value.atom )
506
if ( FT_STRDUP( face->charset_encoding,
507
charset_encoding->value.atom ) ||
508
FT_STRDUP( face->charset_registry,
509
charset_registry->value.atom ) )
512
/* Uh, oh, compare first letters manually to avoid dependency */
514
s = face->charset_registry;
515
if ( ( s[0] == 'i' || s[0] == 'I' ) &&
516
( s[1] == 's' || s[1] == 'S' ) &&
517
( s[2] == 'o' || s[2] == 'O' ) )
520
if ( !ft_strcmp( s, "10646" ) ||
521
( !ft_strcmp( s, "8859" ) &&
522
!ft_strcmp( face->charset_encoding, "1" ) ) )
527
FT_CharMapRec charmap;
530
charmap.face = FT_FACE( face );
531
charmap.encoding = FT_ENCODING_NONE;
532
charmap.platform_id = 0;
533
charmap.encoding_id = 0;
535
if ( unicode_charmap )
537
charmap.encoding = FT_ENCODING_UNICODE;
538
charmap.platform_id = 3;
539
charmap.encoding_id = 1;
542
error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
545
/* Select default charmap */
546
if ( bdfface->num_charmaps )
547
bdfface->charmap = bdfface->charmaps[0];
555
/* otherwise assume Adobe standard encoding */
558
FT_CharMapRec charmap;
561
charmap.face = FT_FACE( face );
562
charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
563
charmap.platform_id = 7;
564
charmap.encoding_id = 0;
566
error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
568
/* Select default charmap */
569
if ( bdfface->num_charmaps )
570
bdfface->charmap = bdfface->charmaps[0];
579
BDF_Face_Done( bdfface );
580
return BDF_Err_Unknown_File_Format;
584
FT_CALLBACK_DEF( FT_Error )
585
BDF_Size_Select( FT_Size size,
586
FT_ULong strike_index )
588
bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;
591
FT_Select_Metrics( size->face, strike_index );
593
size->metrics.ascender = bdffont->font_ascent << 6;
594
size->metrics.descender = -bdffont->font_descent << 6;
595
size->metrics.max_advance = bdffont->bbx.width << 6;
601
FT_CALLBACK_DEF( FT_Error )
602
BDF_Size_Request( FT_Size size,
603
FT_Size_Request req )
605
FT_Face face = size->face;
606
FT_Bitmap_Size* bsize = face->available_sizes;
607
bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;
608
FT_Error error = BDF_Err_Invalid_Pixel_Size;
612
height = FT_REQUEST_HEIGHT( req );
613
height = ( height + 32 ) >> 6;
617
case FT_SIZE_REQUEST_TYPE_NOMINAL:
618
if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
622
case FT_SIZE_REQUEST_TYPE_REAL_DIM:
623
if ( height == ( bdffont->font_ascent +
624
bdffont->font_descent ) )
629
error = BDF_Err_Unimplemented_Feature;
636
return BDF_Size_Select( size, 0 );
641
FT_CALLBACK_DEF( FT_Error )
642
BDF_Glyph_Load( FT_GlyphSlot slot,
645
FT_Int32 load_flags )
647
BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size );
648
FT_Face face = FT_FACE( bdf );
649
FT_Error error = BDF_Err_Ok;
650
FT_Bitmap* bitmap = &slot->bitmap;
652
int bpp = bdf->bdffont->bpp;
654
FT_UNUSED( load_flags );
657
if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
659
error = BDF_Err_Invalid_Argument;
663
/* index 0 is the undefined glyph */
664
if ( glyph_index == 0 )
665
glyph_index = bdf->default_glyph;
669
/* slot, bitmap => freetype, glyph => bdflib */
670
glyph = bdf->bdffont->glyphs[glyph_index];
672
bitmap->rows = glyph.bbx.height;
673
bitmap->width = glyph.bbx.width;
674
bitmap->pitch = glyph.bpr;
676
/* note: we don't allocate a new array to hold the bitmap; */
677
/* we can simply point to it */
678
ft_glyphslot_set_bitmap( slot, glyph.bitmap );
683
bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
686
bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
689
bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
692
bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
693
bitmap->num_grays = 256;
697
slot->format = FT_GLYPH_FORMAT_BITMAP;
698
slot->bitmap_left = glyph.bbx.x_offset;
699
slot->bitmap_top = glyph.bbx.ascent;
701
slot->metrics.horiAdvance = glyph.dwidth << 6;
702
slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
703
slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
704
slot->metrics.width = bitmap->width << 6;
705
slot->metrics.height = bitmap->rows << 6;
708
* XXX DWIDTH1 and VVECTOR should be parsed and
709
* used here, provided such fonts do exist.
711
ft_synthesize_vertical_metrics( &slot->metrics,
712
bdf->bdffont->bbx.height << 6 );
726
bdf_get_bdf_property( BDF_Face face,
727
const char* prop_name,
728
BDF_PropertyRec *aproperty )
730
bdf_property_t* prop;
733
FT_ASSERT( face && face->bdffont );
735
prop = bdf_get_font_property( face->bdffont, prop_name );
738
switch ( prop->format )
741
aproperty->type = BDF_PROPERTY_TYPE_ATOM;
742
aproperty->u.atom = prop->value.atom;
746
aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
747
aproperty->u.integer = prop->value.int32;
751
aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
752
aproperty->u.cardinal = prop->value.card32;
762
return BDF_Err_Invalid_Argument;
767
bdf_get_charset_id( BDF_Face face,
768
const char* *acharset_encoding,
769
const char* *acharset_registry )
771
*acharset_encoding = face->charset_encoding;
772
*acharset_registry = face->charset_registry;
778
static const FT_Service_BDFRec bdf_service_bdf =
780
(FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
781
(FT_BDF_GetPropertyFunc) bdf_get_bdf_property
791
static const FT_ServiceDescRec bdf_services[] =
793
{ FT_SERVICE_ID_BDF, &bdf_service_bdf },
794
{ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
799
FT_CALLBACK_DEF( FT_Module_Interface )
800
bdf_driver_requester( FT_Module module,
805
return ft_service_list_lookup( bdf_services, name );
810
FT_CALLBACK_TABLE_DEF
811
const FT_Driver_ClassRec bdf_driver_class =
814
FT_MODULE_FONT_DRIVER |
815
FT_MODULE_DRIVER_NO_OUTLINES,
816
sizeof ( FT_DriverRec ),
824
(FT_Module_Constructor)0,
825
(FT_Module_Destructor) 0,
826
(FT_Module_Requester) bdf_driver_requester
829
sizeof ( BDF_FaceRec ),
830
sizeof ( FT_SizeRec ),
831
sizeof ( FT_GlyphSlotRec ),
835
0, /* FT_Size_InitFunc */
836
0, /* FT_Size_DoneFunc */
837
0, /* FT_Slot_InitFunc */
838
0, /* FT_Slot_DoneFunc */
840
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
841
ft_stub_set_char_sizes,
842
ft_stub_set_pixel_sizes,
846
0, /* FT_Face_GetKerningFunc */
847
0, /* FT_Face_AttachFunc */
848
0, /* FT_Face_GetAdvancesFunc */