* Sync the recent cmake branch changes.
[reactos.git] / lib / 3rdparty / freetype / src / bdf / bdfdrivr.c
1 /* bdfdrivr.c
2
3 FreeType font driver for bdf files
4
5 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by
6 Francesco Zappa Nardelli
7
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:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
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
24 THE SOFTWARE.
25 */
26
27 #include <ft2build.h>
28
29 #include FT_INTERNAL_DEBUG_H
30 #include FT_INTERNAL_STREAM_H
31 #include FT_INTERNAL_OBJECTS_H
32 #include FT_BDF_H
33 #include FT_TRUETYPE_IDS_H
34
35 #include FT_SERVICE_BDF_H
36 #include FT_SERVICE_XFREE86_NAME_H
37
38 #include "bdf.h"
39 #include "bdfdrivr.h"
40
41 #include "bdferror.h"
42
43
44 /*************************************************************************/
45 /* */
46 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
47 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
48 /* messages during execution. */
49 /* */
50 #undef FT_COMPONENT
51 #define FT_COMPONENT trace_bdfdriver
52
53
54 typedef struct BDF_CMapRec_
55 {
56 FT_CMapRec cmap;
57 FT_ULong num_encodings; /* ftobjs.h: FT_CMap->clazz->size */
58 BDF_encoding_el* encodings;
59
60 } BDF_CMapRec, *BDF_CMap;
61
62
63 FT_CALLBACK_DEF( FT_Error )
64 bdf_cmap_init( FT_CMap bdfcmap,
65 FT_Pointer init_data )
66 {
67 BDF_CMap cmap = (BDF_CMap)bdfcmap;
68 BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap );
69 FT_UNUSED( init_data );
70
71
72 cmap->num_encodings = face->bdffont->glyphs_used;
73 cmap->encodings = face->en_table;
74
75 return BDF_Err_Ok;
76 }
77
78
79 FT_CALLBACK_DEF( void )
80 bdf_cmap_done( FT_CMap bdfcmap )
81 {
82 BDF_CMap cmap = (BDF_CMap)bdfcmap;
83
84
85 cmap->encodings = NULL;
86 cmap->num_encodings = 0;
87 }
88
89
90 FT_CALLBACK_DEF( FT_UInt )
91 bdf_cmap_char_index( FT_CMap bdfcmap,
92 FT_UInt32 charcode )
93 {
94 BDF_CMap cmap = (BDF_CMap)bdfcmap;
95 BDF_encoding_el* encodings = cmap->encodings;
96 FT_ULong min, max, mid; /* num_encodings */
97 FT_UShort result = 0; /* encodings->glyph */
98
99
100 min = 0;
101 max = cmap->num_encodings;
102
103 while ( min < max )
104 {
105 FT_ULong code;
106
107
108 mid = ( min + max ) >> 1;
109 code = encodings[mid].enc;
110
111 if ( charcode == code )
112 {
113 /* increase glyph index by 1 -- */
114 /* we reserve slot 0 for the undefined glyph */
115 result = encodings[mid].glyph + 1;
116 break;
117 }
118
119 if ( charcode < code )
120 max = mid;
121 else
122 min = mid + 1;
123 }
124
125 return result;
126 }
127
128
129 FT_CALLBACK_DEF( FT_UInt )
130 bdf_cmap_char_next( FT_CMap bdfcmap,
131 FT_UInt32 *acharcode )
132 {
133 BDF_CMap cmap = (BDF_CMap)bdfcmap;
134 BDF_encoding_el* encodings = cmap->encodings;
135 FT_ULong min, max, mid; /* num_encodings */
136 FT_UShort result = 0; /* encodings->glyph */
137 FT_ULong charcode = *acharcode + 1;
138
139
140 min = 0;
141 max = cmap->num_encodings;
142
143 while ( min < max )
144 {
145 FT_ULong code; /* same as BDF_encoding_el.enc */
146
147
148 mid = ( min + max ) >> 1;
149 code = encodings[mid].enc;
150
151 if ( charcode == code )
152 {
153 /* increase glyph index by 1 -- */
154 /* we reserve slot 0 for the undefined glyph */
155 result = encodings[mid].glyph + 1;
156 goto Exit;
157 }
158
159 if ( charcode < code )
160 max = mid;
161 else
162 min = mid + 1;
163 }
164
165 charcode = 0;
166 if ( min < cmap->num_encodings )
167 {
168 charcode = encodings[min].enc;
169 result = encodings[min].glyph + 1;
170 }
171
172 Exit:
173 if ( charcode > 0xFFFFFFFFUL )
174 {
175 FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%x > 32bit API" ));
176 *acharcode = 0;
177 /* XXX: result should be changed to indicate an overflow error */
178 }
179 else
180 *acharcode = (FT_UInt32)charcode;
181 return result;
182 }
183
184
185 FT_CALLBACK_TABLE_DEF
186 const FT_CMap_ClassRec bdf_cmap_class =
187 {
188 sizeof ( BDF_CMapRec ),
189 bdf_cmap_init,
190 bdf_cmap_done,
191 bdf_cmap_char_index,
192 bdf_cmap_char_next,
193
194 NULL, NULL, NULL, NULL, NULL
195 };
196
197
198 static FT_Error
199 bdf_interpret_style( BDF_Face bdf )
200 {
201 FT_Error error = BDF_Err_Ok;
202 FT_Face face = FT_FACE( bdf );
203 FT_Memory memory = face->memory;
204 bdf_font_t* font = bdf->bdffont;
205 bdf_property_t* prop;
206
207 char* strings[4] = { NULL, NULL, NULL, NULL };
208 size_t nn, len, lengths[4];
209
210
211 face->style_flags = 0;
212
213 prop = bdf_get_font_property( font, (char *)"SLANT" );
214 if ( prop && prop->format == BDF_ATOM &&
215 prop->value.atom &&
216 ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
217 *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
218 {
219 face->style_flags |= FT_STYLE_FLAG_ITALIC;
220 strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
221 ? (char *)"Oblique"
222 : (char *)"Italic";
223 }
224
225 prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );
226 if ( prop && prop->format == BDF_ATOM &&
227 prop->value.atom &&
228 ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
229 {
230 face->style_flags |= FT_STYLE_FLAG_BOLD;
231 strings[1] = (char *)"Bold";
232 }
233
234 prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" );
235 if ( prop && prop->format == BDF_ATOM &&
236 prop->value.atom && *(prop->value.atom) &&
237 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
238 strings[3] = (char *)(prop->value.atom);
239
240 prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" );
241 if ( prop && prop->format == BDF_ATOM &&
242 prop->value.atom && *(prop->value.atom) &&
243 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
244 strings[0] = (char *)(prop->value.atom);
245
246 len = 0;
247
248 for ( len = 0, nn = 0; nn < 4; nn++ )
249 {
250 lengths[nn] = 0;
251 if ( strings[nn] )
252 {
253 lengths[nn] = ft_strlen( strings[nn] );
254 len += lengths[nn] + 1;
255 }
256 }
257
258 if ( len == 0 )
259 {
260 strings[0] = (char *)"Regular";
261 lengths[0] = ft_strlen( strings[0] );
262 len = lengths[0] + 1;
263 }
264
265 {
266 char* s;
267
268
269 if ( FT_ALLOC( face->style_name, len ) )
270 return error;
271
272 s = face->style_name;
273
274 for ( nn = 0; nn < 4; nn++ )
275 {
276 char* src = strings[nn];
277
278
279 len = lengths[nn];
280
281 if ( src == NULL )
282 continue;
283
284 /* separate elements with a space */
285 if ( s != face->style_name )
286 *s++ = ' ';
287
288 ft_memcpy( s, src, len );
289
290 /* need to convert spaces to dashes for */
291 /* add_style_name and setwidth_name */
292 if ( nn == 0 || nn == 3 )
293 {
294 size_t mm;
295
296
297 for ( mm = 0; mm < len; mm++ )
298 if ( s[mm] == ' ' )
299 s[mm] = '-';
300 }
301
302 s += len;
303 }
304 *s = 0;
305 }
306
307 return error;
308 }
309
310
311 FT_CALLBACK_DEF( void )
312 BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */
313 {
314 BDF_Face face = (BDF_Face)bdfface;
315 FT_Memory memory;
316
317
318 if ( !face )
319 return;
320
321 memory = FT_FACE_MEMORY( face );
322
323 bdf_free_font( face->bdffont );
324
325 FT_FREE( face->en_table );
326
327 FT_FREE( face->charset_encoding );
328 FT_FREE( face->charset_registry );
329 FT_FREE( bdfface->family_name );
330 FT_FREE( bdfface->style_name );
331
332 FT_FREE( bdfface->available_sizes );
333
334 FT_FREE( face->bdffont );
335
336 FT_TRACE4(( "BDF_Face_Done: done face\n" ));
337 }
338
339
340 FT_CALLBACK_DEF( FT_Error )
341 BDF_Face_Init( FT_Stream stream,
342 FT_Face bdfface, /* BDF_Face */
343 FT_Int face_index,
344 FT_Int num_params,
345 FT_Parameter* params )
346 {
347 FT_Error error = BDF_Err_Ok;
348 BDF_Face face = (BDF_Face)bdfface;
349 FT_Memory memory = FT_FACE_MEMORY( face );
350
351 bdf_font_t* font = NULL;
352 bdf_options_t options;
353
354 FT_UNUSED( num_params );
355 FT_UNUSED( params );
356 FT_UNUSED( face_index );
357
358
359 if ( FT_STREAM_SEEK( 0 ) )
360 goto Exit;
361
362 options.correct_metrics = 1; /* FZ XXX: options semantics */
363 options.keep_unencoded = 1;
364 options.keep_comments = 0;
365 options.font_spacing = BDF_PROPORTIONAL;
366
367 error = bdf_load_font( stream, memory, &options, &font );
368 if ( error == BDF_Err_Missing_Startfont_Field )
369 {
370 FT_TRACE2(( "[not a valid BDF file]\n" ));
371 goto Fail;
372 }
373 else if ( error )
374 goto Exit;
375
376 /* we have a bdf font: let's construct the face object */
377 face->bdffont = font;
378 {
379 bdf_property_t* prop = NULL;
380
381
382 FT_TRACE4(( "number of glyphs: %d (%d)\n",
383 font->glyphs_size,
384 font->glyphs_used ));
385 FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n",
386 font->unencoded_size,
387 font->unencoded_used ));
388
389 bdfface->num_faces = 1;
390 bdfface->face_index = 0;
391 bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES |
392 FT_FACE_FLAG_HORIZONTAL |
393 FT_FACE_FLAG_FAST_GLYPHS;
394
395 prop = bdf_get_font_property( font, "SPACING" );
396 if ( prop && prop->format == BDF_ATOM &&
397 prop->value.atom &&
398 ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
399 *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
400 bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
401
402 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
403 /* FZ XXX: I need a font to implement this */
404
405 prop = bdf_get_font_property( font, "FAMILY_NAME" );
406 if ( prop && prop->value.atom )
407 {
408 if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
409 goto Exit;
410 }
411 else
412 bdfface->family_name = 0;
413
414 if ( ( error = bdf_interpret_style( face ) ) != 0 )
415 goto Exit;
416
417 /* the number of glyphs (with one slot for the undefined glyph */
418 /* at position 0 and all unencoded glyphs) */
419 bdfface->num_glyphs = font->glyphs_size + 1;
420
421 bdfface->num_fixed_sizes = 1;
422 if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
423 goto Exit;
424
425 {
426 FT_Bitmap_Size* bsize = bdfface->available_sizes;
427 FT_Short resolution_x = 0, resolution_y = 0;
428
429
430 FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
431
432 bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
433
434 prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
435 if ( prop )
436 bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
437 else
438 bsize->width = (FT_Short)( bsize->height * 2/3 );
439
440 prop = bdf_get_font_property( font, "POINT_SIZE" );
441 if ( prop )
442 /* convert from 722.7 decipoints to 72 points per inch */
443 bsize->size =
444 (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
445 else
446 bsize->size = bsize->width << 6;
447
448 prop = bdf_get_font_property( font, "PIXEL_SIZE" );
449 if ( prop )
450 bsize->y_ppem = (FT_Short)prop->value.l << 6;
451
452 prop = bdf_get_font_property( font, "RESOLUTION_X" );
453 if ( prop )
454 resolution_x = (FT_Short)prop->value.l;
455
456 prop = bdf_get_font_property( font, "RESOLUTION_Y" );
457 if ( prop )
458 resolution_y = (FT_Short)prop->value.l;
459
460 if ( bsize->y_ppem == 0 )
461 {
462 bsize->y_ppem = bsize->size;
463 if ( resolution_y )
464 bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
465 }
466 if ( resolution_x && resolution_y )
467 bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
468 else
469 bsize->x_ppem = bsize->y_ppem;
470 }
471
472 /* encoding table */
473 {
474 bdf_glyph_t* cur = font->glyphs;
475 unsigned long n;
476
477
478 if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
479 goto Exit;
480
481 face->default_glyph = 0;
482 for ( n = 0; n < font->glyphs_size; n++ )
483 {
484 (face->en_table[n]).enc = cur[n].encoding;
485 FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding ));
486 (face->en_table[n]).glyph = (FT_Short)n;
487
488 if ( cur[n].encoding == font->default_char )
489 {
490 if ( n < FT_UINT_MAX )
491 face->default_glyph = (FT_UInt)n;
492 else
493 FT_TRACE1(( "idx %d is too large for this system\n", n ));
494 }
495 }
496 }
497
498 /* charmaps */
499 {
500 bdf_property_t *charset_registry = 0, *charset_encoding = 0;
501 FT_Bool unicode_charmap = 0;
502
503
504 charset_registry =
505 bdf_get_font_property( font, "CHARSET_REGISTRY" );
506 charset_encoding =
507 bdf_get_font_property( font, "CHARSET_ENCODING" );
508 if ( charset_registry && charset_encoding )
509 {
510 if ( charset_registry->format == BDF_ATOM &&
511 charset_encoding->format == BDF_ATOM &&
512 charset_registry->value.atom &&
513 charset_encoding->value.atom )
514 {
515 const char* s;
516
517
518 if ( FT_STRDUP( face->charset_encoding,
519 charset_encoding->value.atom ) ||
520 FT_STRDUP( face->charset_registry,
521 charset_registry->value.atom ) )
522 goto Exit;
523
524 /* Uh, oh, compare first letters manually to avoid dependency */
525 /* on locales. */
526 s = face->charset_registry;
527 if ( ( s[0] == 'i' || s[0] == 'I' ) &&
528 ( s[1] == 's' || s[1] == 'S' ) &&
529 ( s[2] == 'o' || s[2] == 'O' ) )
530 {
531 s += 3;
532 if ( !ft_strcmp( s, "10646" ) ||
533 ( !ft_strcmp( s, "8859" ) &&
534 !ft_strcmp( face->charset_encoding, "1" ) ) )
535 unicode_charmap = 1;
536 }
537
538 {
539 FT_CharMapRec charmap;
540
541
542 charmap.face = FT_FACE( face );
543 charmap.encoding = FT_ENCODING_NONE;
544 /* initial platform/encoding should indicate unset status? */
545 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
546 charmap.encoding_id = TT_APPLE_ID_DEFAULT;
547
548 if ( unicode_charmap )
549 {
550 charmap.encoding = FT_ENCODING_UNICODE;
551 charmap.platform_id = TT_PLATFORM_MICROSOFT;
552 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
553 }
554
555 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
556
557 #if 0
558 /* Select default charmap */
559 if ( bdfface->num_charmaps )
560 bdfface->charmap = bdfface->charmaps[0];
561 #endif
562 }
563
564 goto Exit;
565 }
566 }
567
568 /* otherwise assume Adobe standard encoding */
569
570 {
571 FT_CharMapRec charmap;
572
573
574 charmap.face = FT_FACE( face );
575 charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
576 charmap.platform_id = TT_PLATFORM_ADOBE;
577 charmap.encoding_id = TT_ADOBE_ID_STANDARD;
578
579 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
580
581 /* Select default charmap */
582 if ( bdfface->num_charmaps )
583 bdfface->charmap = bdfface->charmaps[0];
584 }
585 }
586 }
587
588 Exit:
589 return error;
590
591 Fail:
592 BDF_Face_Done( bdfface );
593 return BDF_Err_Unknown_File_Format;
594 }
595
596
597 FT_CALLBACK_DEF( FT_Error )
598 BDF_Size_Select( FT_Size size,
599 FT_ULong strike_index )
600 {
601 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;
602
603
604 FT_Select_Metrics( size->face, strike_index );
605
606 size->metrics.ascender = bdffont->font_ascent << 6;
607 size->metrics.descender = -bdffont->font_descent << 6;
608 size->metrics.max_advance = bdffont->bbx.width << 6;
609
610 return BDF_Err_Ok;
611 }
612
613
614 FT_CALLBACK_DEF( FT_Error )
615 BDF_Size_Request( FT_Size size,
616 FT_Size_Request req )
617 {
618 FT_Face face = size->face;
619 FT_Bitmap_Size* bsize = face->available_sizes;
620 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;
621 FT_Error error = BDF_Err_Invalid_Pixel_Size;
622 FT_Long height;
623
624
625 height = FT_REQUEST_HEIGHT( req );
626 height = ( height + 32 ) >> 6;
627
628 switch ( req->type )
629 {
630 case FT_SIZE_REQUEST_TYPE_NOMINAL:
631 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
632 error = BDF_Err_Ok;
633 break;
634
635 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
636 if ( height == ( bdffont->font_ascent +
637 bdffont->font_descent ) )
638 error = BDF_Err_Ok;
639 break;
640
641 default:
642 error = BDF_Err_Unimplemented_Feature;
643 break;
644 }
645
646 if ( error )
647 return error;
648 else
649 return BDF_Size_Select( size, 0 );
650 }
651
652
653
654 FT_CALLBACK_DEF( FT_Error )
655 BDF_Glyph_Load( FT_GlyphSlot slot,
656 FT_Size size,
657 FT_UInt glyph_index,
658 FT_Int32 load_flags )
659 {
660 BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size );
661 FT_Face face = FT_FACE( bdf );
662 FT_Error error = BDF_Err_Ok;
663 FT_Bitmap* bitmap = &slot->bitmap;
664 bdf_glyph_t glyph;
665 int bpp = bdf->bdffont->bpp;
666
667 FT_UNUSED( load_flags );
668
669
670 if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
671 {
672 error = BDF_Err_Invalid_Argument;
673 goto Exit;
674 }
675
676 /* index 0 is the undefined glyph */
677 if ( glyph_index == 0 )
678 glyph_index = bdf->default_glyph;
679 else
680 glyph_index--;
681
682 /* slot, bitmap => freetype, glyph => bdflib */
683 glyph = bdf->bdffont->glyphs[glyph_index];
684
685 bitmap->rows = glyph.bbx.height;
686 bitmap->width = glyph.bbx.width;
687 if ( glyph.bpr > INT_MAX )
688 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
689 glyph.bpr ));
690 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
691
692 /* note: we don't allocate a new array to hold the bitmap; */
693 /* we can simply point to it */
694 ft_glyphslot_set_bitmap( slot, glyph.bitmap );
695
696 switch ( bpp )
697 {
698 case 1:
699 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
700 break;
701 case 2:
702 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
703 break;
704 case 4:
705 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
706 break;
707 case 8:
708 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
709 bitmap->num_grays = 256;
710 break;
711 }
712
713 slot->format = FT_GLYPH_FORMAT_BITMAP;
714 slot->bitmap_left = glyph.bbx.x_offset;
715 slot->bitmap_top = glyph.bbx.ascent;
716
717 slot->metrics.horiAdvance = glyph.dwidth << 6;
718 slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
719 slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
720 slot->metrics.width = bitmap->width << 6;
721 slot->metrics.height = bitmap->rows << 6;
722
723 /*
724 * XXX DWIDTH1 and VVECTOR should be parsed and
725 * used here, provided such fonts do exist.
726 */
727 ft_synthesize_vertical_metrics( &slot->metrics,
728 bdf->bdffont->bbx.height << 6 );
729
730 Exit:
731 return error;
732 }
733
734
735 /*
736 *
737 * BDF SERVICE
738 *
739 */
740
741 static FT_Error
742 bdf_get_bdf_property( BDF_Face face,
743 const char* prop_name,
744 BDF_PropertyRec *aproperty )
745 {
746 bdf_property_t* prop;
747
748
749 FT_ASSERT( face && face->bdffont );
750
751 prop = bdf_get_font_property( face->bdffont, prop_name );
752 if ( prop )
753 {
754 switch ( prop->format )
755 {
756 case BDF_ATOM:
757 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
758 aproperty->u.atom = prop->value.atom;
759 break;
760
761 case BDF_INTEGER:
762 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
763 {
764 FT_TRACE1(( "bdf_get_bdf_property: " ));
765 FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
766 }
767 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
768 aproperty->u.integer = (FT_Int32)prop->value.l;
769 break;
770
771 case BDF_CARDINAL:
772 if ( prop->value.ul > 0xFFFFFFFFUL )
773 {
774 FT_TRACE1(( "bdf_get_bdf_property: " ));
775 FT_TRACE1(( "too large cardinal 0x%x is truncated\n" ));
776 }
777 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
778 aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
779 break;
780
781 default:
782 goto Fail;
783 }
784 return 0;
785 }
786
787 Fail:
788 return BDF_Err_Invalid_Argument;
789 }
790
791
792 static FT_Error
793 bdf_get_charset_id( BDF_Face face,
794 const char* *acharset_encoding,
795 const char* *acharset_registry )
796 {
797 *acharset_encoding = face->charset_encoding;
798 *acharset_registry = face->charset_registry;
799
800 return 0;
801 }
802
803
804 static const FT_Service_BDFRec bdf_service_bdf =
805 {
806 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
807 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
808 };
809
810
811 /*
812 *
813 * SERVICES LIST
814 *
815 */
816
817 static const FT_ServiceDescRec bdf_services[] =
818 {
819 { FT_SERVICE_ID_BDF, &bdf_service_bdf },
820 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
821 { NULL, NULL }
822 };
823
824
825 FT_CALLBACK_DEF( FT_Module_Interface )
826 bdf_driver_requester( FT_Module module,
827 const char* name )
828 {
829 FT_UNUSED( module );
830
831 return ft_service_list_lookup( bdf_services, name );
832 }
833
834
835
836 FT_CALLBACK_TABLE_DEF
837 const FT_Driver_ClassRec bdf_driver_class =
838 {
839 {
840 FT_MODULE_FONT_DRIVER |
841 FT_MODULE_DRIVER_NO_OUTLINES,
842 sizeof ( FT_DriverRec ),
843
844 "bdf",
845 0x10000L,
846 0x20000L,
847
848 0,
849
850 (FT_Module_Constructor)0,
851 (FT_Module_Destructor) 0,
852 (FT_Module_Requester) bdf_driver_requester
853 },
854
855 sizeof ( BDF_FaceRec ),
856 sizeof ( FT_SizeRec ),
857 sizeof ( FT_GlyphSlotRec ),
858
859 BDF_Face_Init,
860 BDF_Face_Done,
861 0, /* FT_Size_InitFunc */
862 0, /* FT_Size_DoneFunc */
863 0, /* FT_Slot_InitFunc */
864 0, /* FT_Slot_DoneFunc */
865
866 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
867 ft_stub_set_char_sizes,
868 ft_stub_set_pixel_sizes,
869 #endif
870 BDF_Glyph_Load,
871
872 0, /* FT_Face_GetKerningFunc */
873 0, /* FT_Face_AttachFunc */
874 0, /* FT_Face_GetAdvancesFunc */
875
876 BDF_Size_Request,
877 BDF_Size_Select
878 };
879
880
881 /* END */