3 FreeType font driver for bdf files
5 Copyright (C) 2001-2002 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
40 /*************************************************************************/
42 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
43 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
44 /* messages during execution. */
47 #define FT_COMPONENT trace_bdfdriver
50 typedef struct BDF_CMapRec_
53 FT_UInt num_encodings;
54 BDF_encoding_el* encodings;
56 } BDF_CMapRec, *BDF_CMap;
59 FT_CALLBACK_DEF( FT_Error )
60 bdf_cmap_init( BDF_CMap cmap )
62 BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap );
65 cmap->num_encodings = face->bdffont->glyphs_used;
66 cmap->encodings = face->en_table;
72 FT_CALLBACK_DEF( void )
73 bdf_cmap_done( BDF_CMap cmap )
75 cmap->encodings = NULL;
76 cmap->num_encodings = 0;
80 FT_CALLBACK_DEF( FT_UInt )
81 bdf_cmap_char_index( BDF_CMap cmap,
84 BDF_encoding_el* encodings = cmap->encodings;
85 FT_UInt min, max, mid;
90 max = cmap->num_encodings;
97 mid = ( min + max ) >> 1;
98 code = encodings[mid].enc;
100 if ( charcode == code )
102 result = encodings[mid].glyph + 1;
106 if ( charcode < code )
116 FT_CALLBACK_DEF( FT_UInt )
117 bdf_cmap_char_next( BDF_CMap cmap,
118 FT_UInt32 *acharcode )
120 BDF_encoding_el* encodings = cmap->encodings;
121 FT_UInt min, max, mid;
122 FT_UInt32 charcode = *acharcode + 1;
127 max = cmap->num_encodings;
134 mid = ( min + max ) >> 1;
135 code = encodings[mid].enc;
137 if ( charcode == code )
139 result = encodings[mid].glyph + 1;
143 if ( charcode < code )
150 if ( min < cmap->num_encodings )
152 charcode = encodings[min].enc;
153 result = encodings[min].glyph + 1;
157 *acharcode = charcode;
162 FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec bdf_cmap_class =
164 sizeof( BDF_CMapRec ),
165 (FT_CMap_InitFunc) bdf_cmap_init,
166 (FT_CMap_DoneFunc) bdf_cmap_done,
167 (FT_CMap_CharIndexFunc)bdf_cmap_char_index,
168 (FT_CMap_CharNextFunc) bdf_cmap_char_next
174 FT_CALLBACK_DEF( FT_Error )
175 BDF_Face_Done( BDF_Face face )
177 FT_Memory memory = FT_FACE_MEMORY( face );
180 bdf_free_font( face->bdffont );
182 FT_FREE( face->en_table );
184 FT_FREE( face->charset_encoding );
185 FT_FREE( face->charset_registry );
186 FT_FREE( face->root.family_name );
188 FT_FREE( face->root.available_sizes );
190 FT_FREE( face->bdffont );
192 FT_TRACE4(( "BDF_Face_Done: done face\n" ));
198 FT_CALLBACK_DEF( FT_Error )
199 BDF_Face_Init( FT_Stream stream,
203 FT_Parameter* params )
205 FT_Error error = BDF_Err_Ok;
206 FT_Memory memory = FT_FACE_MEMORY( face );
209 bdf_options_t options;
211 FT_UNUSED( num_params );
213 FT_UNUSED( face_index );
216 if ( FT_STREAM_SEEK( 0 ) )
219 options.correct_metrics = 1; /* FZ XXX: options semantics */
220 options.keep_unencoded = 1;
221 options.keep_comments = 0;
222 options.font_spacing = BDF_PROPORTIONAL;
224 error = bdf_load_font( stream, memory, &options, &font );
225 if ( error == BDF_Err_Missing_Startfont_Field )
227 FT_TRACE2(( "[not a valid BDF file]\n" ));
233 /* we have a bdf font: let's construct the face object */
234 face->bdffont = font;
236 FT_Face root = FT_FACE( face );
237 bdf_property_t* prop = NULL;
240 FT_TRACE4(( "number of glyphs: %d (%d)\n",
242 font->glyphs_used ));
243 FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",
244 font->unencoded_size,
245 font->unencoded_used ));
248 root->face_index = 0;
249 root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
250 FT_FACE_FLAG_HORIZONTAL |
251 FT_FACE_FLAG_FAST_GLYPHS;
253 prop = bdf_get_font_property( font, (char *)"SPACING" );
255 if ( prop->format == BDF_ATOM )
256 if ( prop->value.atom != NULL )
257 if ( ( *(prop->value.atom) == 'M' ) ||
258 ( *(prop->value.atom) == 'C' ) )
259 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
261 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
262 /* FZ XXX: I need a font to implement this */
264 root->style_flags = 0;
265 prop = bdf_get_font_property( font, (char *)"SLANT" );
267 if ( prop->format == BDF_ATOM )
268 if ( prop->value.atom != NULL )
269 if ( ( *(prop->value.atom) == 'O' ) ||
270 ( *(prop->value.atom) == 'I' ) )
271 root->style_flags |= FT_STYLE_FLAG_ITALIC;
273 prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );
275 if ( prop->format == BDF_ATOM )
276 if ( prop->value.atom != NULL )
277 if ( *(prop->value.atom) == 'B' )
278 root->style_flags |= FT_STYLE_FLAG_BOLD;
280 prop = bdf_get_font_property( font, (char *)"FAMILY_NAME" );
281 if ( ( prop != NULL ) && ( prop->value.atom != NULL ) )
283 int l = ft_strlen( prop->value.atom ) + 1;
286 if ( FT_NEW_ARRAY( root->family_name, l ) )
288 ft_strcpy( root->family_name, prop->value.atom );
291 root->family_name = 0;
293 root->style_name = (char *)"Regular";
294 if ( root->style_flags & FT_STYLE_FLAG_BOLD )
296 if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
297 root->style_name = (char *)"Bold Italic";
299 root->style_name = (char *)"Bold";
301 else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
302 root->style_name = (char *)"Italic";
304 root->num_glyphs = font->glyphs_size; /* unencoded included */
306 root->num_fixed_sizes = 1;
307 if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
310 prop = bdf_get_font_property( font, (char *)"AVERAGE_WIDTH" );
311 if ( ( prop != NULL ) && ( prop->value.int32 >= 10 ) )
312 root->available_sizes->width = (short)( prop->value.int32 / 10 );
314 prop = bdf_get_font_property( font, (char *)"PIXEL_SIZE" );
316 root->available_sizes->height = (short) prop->value.int32;
319 prop = bdf_get_font_property( font, (char *)"POINT_SIZE" );
322 bdf_property_t *yres;
325 yres = bdf_get_font_property( font, (char *)"RESOLUTION_Y" );
328 FT_TRACE4(( "POINT_SIZE: %d RESOLUTION_Y: %d\n",
329 prop->value.int32, yres->value.int32 ));
330 root->available_sizes->height =
331 (FT_Short)( prop->value.int32 * yres->value.int32 / 720 );
336 if ( root->available_sizes->width == 0 )
338 if ( root->available_sizes->height == 0 )
340 /* some fonts have broken SIZE declaration (jiskan24.bdf) */
341 FT_ERROR(( "BDF_Face_Init: reading size\n" ));
342 root->available_sizes->width = (FT_Short)font->point_size;
345 root->available_sizes->width = root->available_sizes->height;
347 if ( root->available_sizes->height == 0 )
348 root->available_sizes->height = root->available_sizes->width;
352 bdf_glyph_t* cur = font->glyphs;
356 if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
359 for ( n = 0; n < font->glyphs_size; n++ )
361 (face->en_table[n]).enc = cur[n].encoding;
362 FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding ));
363 (face->en_table[n]).glyph = (FT_Short)n;
369 bdf_property_t *charset_registry = 0, *charset_encoding = 0;
370 FT_Bool unicode_charmap = 0;
374 bdf_get_font_property( font, (char *)"CHARSET_REGISTRY" );
376 bdf_get_font_property( font, (char *)"CHARSET_ENCODING" );
377 if ( ( charset_registry != NULL ) && ( charset_encoding != NULL ) )
379 if ( ( charset_registry->format == BDF_ATOM ) &&
380 ( charset_encoding->format == BDF_ATOM ) &&
381 ( charset_registry->value.atom != NULL ) &&
382 ( charset_encoding->value.atom != NULL ) )
384 if ( FT_NEW_ARRAY( face->charset_encoding,
385 strlen( charset_encoding->value.atom ) + 1 ) )
387 if ( FT_NEW_ARRAY( face->charset_registry,
388 strlen( charset_registry->value.atom ) + 1 ) )
390 ft_strcpy( face->charset_registry, charset_registry->value.atom );
391 ft_strcpy( face->charset_encoding, charset_encoding->value.atom );
392 if ( !ft_strcmp( face->charset_registry, "ISO10646" ) ||
393 ( !ft_strcmp( face->charset_registry, "ISO8859" ) &&
394 !ft_strcmp( face->charset_encoding, "1" ) ) )
398 FT_CharMapRec charmap;
401 charmap.face = FT_FACE( face );
402 charmap.encoding = FT_ENCODING_NONE;
403 charmap.platform_id = 0;
404 charmap.encoding_id = 0;
406 if ( unicode_charmap )
408 charmap.encoding = FT_ENCODING_UNICODE;
409 charmap.platform_id = 3;
410 charmap.encoding_id = 1;
413 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
416 /* Select default charmap */
417 if (root->num_charmaps)
418 root->charmap = root->charmaps[0];
426 /* otherwise assume Adobe standard encoding */
429 FT_CharMapRec charmap;
432 charmap.face = FT_FACE( face );
433 charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
434 charmap.platform_id = 7;
435 charmap.encoding_id = 0;
437 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
439 /* Select default charmap */
440 if (root->num_charmaps)
441 root->charmap = root->charmaps[0];
450 BDF_Face_Done( face );
451 return BDF_Err_Unknown_File_Format;
456 BDF_Set_Pixel_Size( FT_Size size )
458 BDF_Face face = (BDF_Face)FT_SIZE_FACE( size );
459 FT_Face root = FT_FACE( face );
462 FT_TRACE4(( "rec %d - pres %d\n",
463 size->metrics.y_ppem, root->available_sizes->height ));
465 if ( size->metrics.y_ppem == root->available_sizes->height )
467 size->metrics.ascender = face->bdffont->bbx.ascent << 6;
468 size->metrics.descender = face->bdffont->bbx.descent * ( -64 );
469 size->metrics.height = face->bdffont->bbx.height << 6;
474 return BDF_Err_Invalid_Pixel_Size;
479 BDF_Glyph_Load( FT_GlyphSlot slot,
482 FT_Int32 load_flags )
484 BDF_Face face = (BDF_Face)FT_SIZE_FACE( size );
485 FT_Error error = BDF_Err_Ok;
486 FT_Bitmap* bitmap = &slot->bitmap;
488 int bpp = face->bdffont->bpp;
490 unsigned char *p, *pp;
492 FT_UNUSED( load_flags );
497 error = BDF_Err_Invalid_Argument;
501 if ( glyph_index > 0 )
504 /* slot, bitmap => freetype, glyph => bdflib */
505 glyph = face->bdffont->glyphs[glyph_index];
507 bitmap->rows = glyph.bbx.height;
508 bitmap->width = glyph.bbx.width;
512 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
513 bitmap->pitch = glyph.bpr;
515 /* note: we don't allocate a new array to hold the bitmap, we */
516 /* can simply point to it */
517 ft_glyphslot_set_bitmap( slot, glyph.bitmap );
521 /* blow up pixmap to have 8 bits per pixel */
522 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
523 bitmap->pitch = bitmap->width;
525 error = ft_glyphslot_alloc_bitmap( slot, bitmap->rows * bitmap->pitch );
532 bitmap->num_grays = 4;
537 for ( i = 0; i < bitmap->rows; i++ )
541 /* get the full bytes */
542 for ( j = 0; j < ( bitmap->width >> 2 ); j++ )
544 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xC0 ) >> 6 );
545 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x30 ) >> 4 );
546 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x0C ) >> 2 );
547 bitmap->buffer[count++] = (FT_Byte)( *pp & 0x03 );
552 /* get remaining pixels (if any) */
553 switch ( bitmap->width & 3 )
556 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xC0 ) >> 6 );
559 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x30 ) >> 4 );
562 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x0C ) >> 2 );
573 bitmap->num_grays = 16;
578 for ( i = 0; i < bitmap->rows; i++ )
582 /* get the full bytes */
583 for ( j = 0; j < ( bitmap->width >> 1 ); j++ )
585 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xF0 ) >> 4 );
586 bitmap->buffer[count++] = (FT_Byte)( *pp & 0x0F );
591 /* get remaining pixel (if any) */
592 switch ( bitmap->width & 1 )
595 bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xF0 ) >> 4 );
606 bitmap->num_grays = 256;
608 FT_MEM_COPY( bitmap->buffer, glyph.bitmap,
609 bitmap->rows * bitmap->pitch );
614 slot->bitmap_left = 0;
615 slot->bitmap_top = glyph.bbx.ascent;
617 /* FZ XXX: TODO: vertical metrics */
618 slot->metrics.horiAdvance = glyph.dwidth << 6;
619 slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
620 slot->metrics.horiBearingY = ( glyph.bbx.y_offset +
621 glyph.bbx.height ) << 6;
622 slot->metrics.width = bitmap->width << 6;
623 slot->metrics.height = bitmap->rows << 6;
625 slot->linearHoriAdvance = (FT_Fixed)glyph.dwidth << 16;
626 slot->format = FT_GLYPH_FORMAT_BITMAP;
634 bdf_get_bdf_property( BDF_Face face,
635 const char* prop_name,
636 BDF_PropertyRec *aproperty )
638 bdf_property_t* prop;
640 FT_ASSERT( face && face->bdffont );
642 prop = bdf_get_font_property( face->bdffont, (char*)prop_name );
645 switch ( prop->format )
648 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
649 aproperty->u.atom = prop->value.atom;
653 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
654 aproperty->u.integer = prop->value.int32;
658 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
659 aproperty->u.cardinal = prop->value.card32;
668 return FT_Err_Invalid_Argument;
672 static FT_Module_Interface
673 bdf_driver_requester( FT_Module module,
678 if ( name && ft_strcmp( name, "get_bdf_property" ) == 0 )
679 return (FT_Module_Interface) bdf_get_bdf_property;
685 FT_CALLBACK_TABLE_DEF
686 const FT_Driver_ClassRec bdf_driver_class =
689 ft_module_font_driver,
690 sizeof ( FT_DriverRec ),
698 (FT_Module_Constructor)0,
699 (FT_Module_Destructor) 0,
700 (FT_Module_Requester) bdf_driver_requester
703 sizeof ( BDF_FaceRec ),
704 sizeof ( FT_SizeRec ),
705 sizeof ( FT_GlyphSlotRec ),
707 (FT_Face_InitFunc) BDF_Face_Init,
708 (FT_Face_DoneFunc) BDF_Face_Done,
709 (FT_Size_InitFunc) 0,
710 (FT_Size_DoneFunc) 0,
711 (FT_Slot_InitFunc) 0,
712 (FT_Slot_DoneFunc) 0,
714 (FT_Size_ResetPointsFunc) BDF_Set_Pixel_Size,
715 (FT_Size_ResetPixelsFunc) BDF_Set_Pixel_Size,
717 (FT_Slot_LoadFunc) BDF_Glyph_Load,
719 (FT_Face_GetKerningFunc) 0,
720 (FT_Face_AttachFunc) 0,
721 (FT_Face_GetAdvancesFunc) 0