3 FreeType font driver for pcf files
5 Copyright (C) 2000-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
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
38 #include "pcfdriver.h"
45 #define FT_COMPONENT trace_pcfread
48 typedef struct PCF_CMapRec_
51 FT_UInt num_encodings;
52 PCF_Encoding encodings;
54 } PCF_CMapRec, *PCF_CMap;
57 FT_CALLBACK_DEF( FT_Error )
58 pcf_cmap_init( PCF_CMap cmap )
60 PCF_Face face = (PCF_Face)FT_CMAP_FACE( cmap );
63 cmap->num_encodings = (FT_UInt)face->nencodings;
64 cmap->encodings = face->encodings;
70 FT_CALLBACK_DEF( void )
71 pcf_cmap_done( PCF_CMap cmap )
73 cmap->encodings = NULL;
74 cmap->num_encodings = 0;
78 FT_CALLBACK_DEF( FT_UInt )
79 pcf_cmap_char_index( PCF_CMap cmap,
82 PCF_Encoding encodings = cmap->encodings;
83 FT_UInt min, max, mid;
88 max = cmap->num_encodings;
95 mid = ( min + max ) >> 1;
96 code = encodings[mid].enc;
98 if ( charcode == code )
100 result = encodings[mid].glyph + 1;
104 if ( charcode < code )
114 FT_CALLBACK_DEF( FT_UInt )
115 pcf_cmap_char_next( PCF_CMap cmap,
116 FT_UInt32 *acharcode )
118 PCF_Encoding encodings = cmap->encodings;
119 FT_UInt min, max, mid;
120 FT_UInt32 charcode = *acharcode + 1;
125 max = cmap->num_encodings;
132 mid = ( min + max ) >> 1;
133 code = encodings[mid].enc;
135 if ( charcode == code )
137 result = encodings[mid].glyph + 1;
141 if ( charcode < code )
148 if ( min < cmap->num_encodings )
150 charcode = encodings[min].enc;
151 result = encodings[min].glyph + 1;
155 *acharcode = charcode;
160 FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec pcf_cmap_class =
162 sizeof( PCF_CMapRec ),
163 (FT_CMap_InitFunc) pcf_cmap_init,
164 (FT_CMap_DoneFunc) pcf_cmap_done,
165 (FT_CMap_CharIndexFunc)pcf_cmap_char_index,
166 (FT_CMap_CharNextFunc) pcf_cmap_char_next
170 /*************************************************************************/
172 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
173 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
174 /* messages during execution. */
177 #define FT_COMPONENT trace_pcfdriver
180 FT_CALLBACK_DEF( FT_Error )
181 PCF_Face_Done( PCF_Face face )
183 FT_Memory memory = FT_FACE_MEMORY( face );
186 FT_FREE( face->encodings );
187 FT_FREE( face->metrics );
189 /* free properties */
191 PCF_Property prop = face->properties;
195 for ( i = 0; i < face->nprops; i++ )
197 prop = &face->properties[i];
199 FT_FREE( prop->name );
200 if ( prop->isString )
201 FT_FREE( prop->value );
204 FT_FREE( face->properties );
207 FT_FREE( face->toc.tables );
208 FT_FREE( face->root.family_name );
209 FT_FREE( face->root.available_sizes );
210 FT_FREE( face->charset_encoding );
211 FT_FREE( face->charset_registry );
213 FT_TRACE4(( "PCF_Face_Done: done face\n" ));
215 /* close gzip stream if any */
216 if ( face->root.stream == &face->gzip_stream )
218 FT_Stream_Close( &face->gzip_stream );
219 face->root.stream = face->gzip_source;
226 FT_CALLBACK_DEF( FT_Error )
227 PCF_Face_Init( FT_Stream stream,
231 FT_Parameter* params )
233 FT_Error error = PCF_Err_Ok;
235 FT_UNUSED( num_params );
237 FT_UNUSED( face_index );
240 error = pcf_load_font( stream, face );
245 /* this didn't work, try gzip support !! */
246 error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
247 if ( error2 == FT_Err_Unimplemented_Feature )
254 face->gzip_source = stream;
255 face->root.stream = &face->gzip_stream;
257 stream = face->root.stream;
259 error = pcf_load_font( stream, face );
266 FT_String *charset_registry, *charset_encoding;
267 FT_Bool unicode_charmap = 0;
270 charset_registry = face->charset_registry;
271 charset_encoding = face->charset_encoding;
273 if ( ( charset_registry != NULL ) &&
274 ( charset_encoding != NULL ) )
276 if ( !ft_strcmp( face->charset_registry, "ISO10646" ) ||
277 ( !ft_strcmp( face->charset_registry, "ISO8859" ) &&
278 !ft_strcmp( face->charset_encoding, "1" ) ) )
283 FT_CharMapRec charmap;
286 charmap.face = FT_FACE( face );
287 charmap.encoding = FT_ENCODING_NONE;
288 charmap.platform_id = 0;
289 charmap.encoding_id = 0;
291 if ( unicode_charmap )
293 charmap.encoding = FT_ENCODING_UNICODE;
294 charmap.platform_id = 3;
295 charmap.encoding_id = 1;
298 error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
301 /* Select default charmap */
302 if (face->root.num_charmaps)
303 face->root.charmap = face->root.charmaps[0];
312 FT_TRACE2(( "[not a valid PCF file]\n" ));
313 error = PCF_Err_Unknown_File_Format; /* error */
319 PCF_Set_Pixel_Size( FT_Size size )
321 PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );
324 FT_TRACE4(( "rec %d - pres %d\n", size->metrics.y_ppem,
325 face->root.available_sizes->height ));
327 if ( size->metrics.y_ppem == face->root.available_sizes->height )
329 size->metrics.ascender = face->accel.fontAscent << 6;
330 size->metrics.descender = face->accel.fontDescent * (-64);
332 size->metrics.height = face->accel.maxbounds.ascent << 6;
334 size->metrics.height = size->metrics.ascender -
335 size->metrics.descender;
337 size->metrics.max_advance = face->accel.maxbounds.characterWidth << 6;
343 FT_TRACE4(( "size WRONG\n" ));
344 return PCF_Err_Invalid_Pixel_Size;
350 PCF_Glyph_Load( FT_GlyphSlot slot,
353 FT_Int32 load_flags )
355 PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );
356 FT_Stream stream = face->root.stream;
357 FT_Error error = PCF_Err_Ok;
358 FT_Bitmap* bitmap = &slot->bitmap;
362 FT_UNUSED( load_flags );
365 FT_TRACE4(( "load_glyph %d ---", glyph_index ));
369 error = PCF_Err_Invalid_Argument;
373 if ( glyph_index > 0 )
376 metric = face->metrics + glyph_index;
378 bitmap->rows = metric->ascent + metric->descent;
379 bitmap->width = metric->rightSideBearing - metric->leftSideBearing;
380 bitmap->num_grays = 1;
381 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
383 FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
384 PCF_BIT_ORDER( face->bitmapsFormat ),
385 PCF_BYTE_ORDER( face->bitmapsFormat ),
386 PCF_GLYPH_PAD( face->bitmapsFormat ) ));
388 switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
391 bitmap->pitch = ( bitmap->width + 7 ) >> 3;
395 bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
399 bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
403 bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
407 return PCF_Err_Invalid_File_Format;
410 /* XXX: to do: are there cases that need repadding the bitmap? */
411 bytes = bitmap->pitch * bitmap->rows;
413 error = ft_glyphslot_alloc_bitmap( slot, bytes );
417 if ( FT_STREAM_SEEK( metric->bits ) ||
418 FT_STREAM_READ( bitmap->buffer, bytes ) )
421 if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
422 BitOrderInvert( bitmap->buffer, bytes );
424 if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
425 PCF_BIT_ORDER( face->bitmapsFormat ) ) )
427 switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
433 TwoByteSwap( bitmap->buffer, bytes );
437 FourByteSwap( bitmap->buffer, bytes );
442 slot->bitmap_left = metric->leftSideBearing;
443 slot->bitmap_top = metric->ascent;
445 slot->metrics.horiAdvance = metric->characterWidth << 6 ;
446 slot->metrics.horiBearingX = metric->leftSideBearing << 6 ;
447 slot->metrics.horiBearingY = metric->ascent << 6 ;
448 slot->metrics.width = ( metric->rightSideBearing -
449 metric->leftSideBearing ) << 6;
450 slot->metrics.height = bitmap->rows << 6;
452 slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
453 slot->format = FT_GLYPH_FORMAT_BITMAP;
455 FT_TRACE4(( " --- ok\n" ));
463 pcf_get_bdf_property( PCF_Face face,
464 const char* prop_name,
465 BDF_PropertyRec *aproperty )
469 prop = pcf_find_property( face, prop_name );
472 if ( prop->isString )
474 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
475 aproperty->u.atom = prop->value.atom;
479 /* apparently, the PCF driver loads all properties as signed integers !
480 * this really doesn't seem to be a problem, because this is
481 * sufficient for any meaningful values
483 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
484 aproperty->u.integer = prop->value.integer;
488 return FT_Err_Invalid_Argument;
492 static FT_Module_Interface
493 pcf_driver_requester( FT_Module module,
498 if ( name && ft_strcmp( name, "get_bdf_property" ) == 0 )
499 return (FT_Module_Interface) pcf_get_bdf_property;
505 FT_CALLBACK_TABLE_DEF
506 const FT_Driver_ClassRec pcf_driver_class =
509 ft_module_font_driver,
510 sizeof ( FT_DriverRec ),
518 (FT_Module_Constructor)0,
519 (FT_Module_Destructor) 0,
520 (FT_Module_Requester) pcf_driver_requester
523 sizeof( PCF_FaceRec ),
524 sizeof( FT_SizeRec ),
525 sizeof( FT_GlyphSlotRec ),
527 (FT_Face_InitFunc) PCF_Face_Init,
528 (FT_Face_DoneFunc) PCF_Face_Done,
529 (FT_Size_InitFunc) 0,
530 (FT_Size_DoneFunc) 0,
531 (FT_Slot_InitFunc) 0,
532 (FT_Slot_DoneFunc) 0,
534 (FT_Size_ResetPointsFunc) PCF_Set_Pixel_Size,
535 (FT_Size_ResetPixelsFunc) PCF_Set_Pixel_Size,
537 (FT_Slot_LoadFunc) PCF_Glyph_Load,
539 (FT_Face_GetKerningFunc) 0,
540 (FT_Face_AttachFunc) 0,
541 (FT_Face_GetAdvancesFunc) 0