0ea0a5ea5eb36ef2675ad714e39a730454177933
[reactos.git] / reactos / lib / 3rdparty / freetype / src / bdf / bdfdrivr.c
1 /* bdfdrivr.c
2
3 FreeType font driver for bdf files
4
5 Copyright (C) 2001-2008, 2011, 2013 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 FT_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 = FT_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
337
338 FT_CALLBACK_DEF( FT_Error )
339 BDF_Face_Init( FT_Stream stream,
340 FT_Face bdfface, /* BDF_Face */
341 FT_Int face_index,
342 FT_Int num_params,
343 FT_Parameter* params )
344 {
345 FT_Error error = FT_Err_Ok;
346 BDF_Face face = (BDF_Face)bdfface;
347 FT_Memory memory = FT_FACE_MEMORY( face );
348
349 bdf_font_t* font = NULL;
350 bdf_options_t options;
351
352 FT_UNUSED( num_params );
353 FT_UNUSED( params );
354 FT_UNUSED( face_index );
355
356
357 FT_TRACE2(( "BDF driver\n" ));
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 ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
369 {
370 FT_TRACE2(( " not a 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: allocated %d (used %d)\n",
383 font->glyphs_size,
384 font->glyphs_used ));
385 FT_TRACE4(( " number of unencoded glyphs: allocated %d (used %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(( "BDF_Face_Init:"
494 " idx %d is too large for this system\n", n ));
495 }
496 }
497 }
498
499 /* charmaps */
500 {
501 bdf_property_t *charset_registry = 0, *charset_encoding = 0;
502 FT_Bool unicode_charmap = 0;
503
504
505 charset_registry =
506 bdf_get_font_property( font, "CHARSET_REGISTRY" );
507 charset_encoding =
508 bdf_get_font_property( font, "CHARSET_ENCODING" );
509 if ( charset_registry && charset_encoding )
510 {
511 if ( charset_registry->format == BDF_ATOM &&
512 charset_encoding->format == BDF_ATOM &&
513 charset_registry->value.atom &&
514 charset_encoding->value.atom )
515 {
516 const char* s;
517
518
519 if ( FT_STRDUP( face->charset_encoding,
520 charset_encoding->value.atom ) ||
521 FT_STRDUP( face->charset_registry,
522 charset_registry->value.atom ) )
523 goto Exit;
524
525 /* Uh, oh, compare first letters manually to avoid dependency */
526 /* on locales. */
527 s = face->charset_registry;
528 if ( ( s[0] == 'i' || s[0] == 'I' ) &&
529 ( s[1] == 's' || s[1] == 'S' ) &&
530 ( s[2] == 'o' || s[2] == 'O' ) )
531 {
532 s += 3;
533 if ( !ft_strcmp( s, "10646" ) ||
534 ( !ft_strcmp( s, "8859" ) &&
535 !ft_strcmp( face->charset_encoding, "1" ) ) )
536 unicode_charmap = 1;
537 }
538
539 {
540 FT_CharMapRec charmap;
541
542
543 charmap.face = FT_FACE( face );
544 charmap.encoding = FT_ENCODING_NONE;
545 /* initial platform/encoding should indicate unset status? */
546 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
547 charmap.encoding_id = TT_APPLE_ID_DEFAULT;
548
549 if ( unicode_charmap )
550 {
551 charmap.encoding = FT_ENCODING_UNICODE;
552 charmap.platform_id = TT_PLATFORM_MICROSOFT;
553 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
554 }
555
556 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
557
558 #if 0
559 /* Select default charmap */
560 if ( bdfface->num_charmaps )
561 bdfface->charmap = bdfface->charmaps[0];
562 #endif
563 }
564
565 goto Exit;
566 }
567 }
568
569 /* otherwise assume Adobe standard encoding */
570
571 {
572 FT_CharMapRec charmap;
573
574
575 charmap.face = FT_FACE( face );
576 charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
577 charmap.platform_id = TT_PLATFORM_ADOBE;
578 charmap.encoding_id = TT_ADOBE_ID_STANDARD;
579
580 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
581
582 /* Select default charmap */
583 if ( bdfface->num_charmaps )
584 bdfface->charmap = bdfface->charmaps[0];
585 }
586 }
587 }
588
589 Exit:
590 return error;
591
592 Fail:
593 BDF_Face_Done( bdfface );
594 return FT_THROW( Unknown_File_Format );
595 }
596
597
598 FT_CALLBACK_DEF( FT_Error )
599 BDF_Size_Select( FT_Size size,
600 FT_ULong strike_index )
601 {
602 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;
603
604
605 FT_Select_Metrics( size->face, strike_index );
606
607 size->metrics.ascender = bdffont->font_ascent << 6;
608 size->metrics.descender = -bdffont->font_descent << 6;
609 size->metrics.max_advance = bdffont->bbx.width << 6;
610
611 return FT_Err_Ok;
612 }
613
614
615 FT_CALLBACK_DEF( FT_Error )
616 BDF_Size_Request( FT_Size size,
617 FT_Size_Request req )
618 {
619 FT_Face face = size->face;
620 FT_Bitmap_Size* bsize = face->available_sizes;
621 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;
622 FT_Error error = FT_ERR( Invalid_Pixel_Size );
623 FT_Long height;
624
625
626 height = FT_REQUEST_HEIGHT( req );
627 height = ( height + 32 ) >> 6;
628
629 switch ( req->type )
630 {
631 case FT_SIZE_REQUEST_TYPE_NOMINAL:
632 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
633 error = FT_Err_Ok;
634 break;
635
636 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
637 if ( height == ( bdffont->font_ascent +
638 bdffont->font_descent ) )
639 error = FT_Err_Ok;
640 break;
641
642 default:
643 error = FT_THROW( Unimplemented_Feature );
644 break;
645 }
646
647 if ( error )
648 return error;
649 else
650 return BDF_Size_Select( size, 0 );
651 }
652
653
654
655 FT_CALLBACK_DEF( FT_Error )
656 BDF_Glyph_Load( FT_GlyphSlot slot,
657 FT_Size size,
658 FT_UInt glyph_index,
659 FT_Int32 load_flags )
660 {
661 BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size );
662 FT_Face face = FT_FACE( bdf );
663 FT_Error error = FT_Err_Ok;
664 FT_Bitmap* bitmap = &slot->bitmap;
665 bdf_glyph_t glyph;
666 int bpp = bdf->bdffont->bpp;
667
668 FT_UNUSED( load_flags );
669
670
671 if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
672 {
673 error = FT_THROW( Invalid_Argument );
674 goto Exit;
675 }
676
677 /* index 0 is the undefined glyph */
678 if ( glyph_index == 0 )
679 glyph_index = bdf->default_glyph;
680 else
681 glyph_index--;
682
683 /* slot, bitmap => freetype, glyph => bdflib */
684 glyph = bdf->bdffont->glyphs[glyph_index];
685
686 bitmap->rows = glyph.bbx.height;
687 bitmap->width = glyph.bbx.width;
688 if ( glyph.bpr > INT_MAX )
689 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
690 glyph.bpr ));
691 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
692
693 /* note: we don't allocate a new array to hold the bitmap; */
694 /* we can simply point to it */
695 ft_glyphslot_set_bitmap( slot, glyph.bitmap );
696
697 switch ( bpp )
698 {
699 case 1:
700 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
701 break;
702 case 2:
703 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
704 break;
705 case 4:
706 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
707 break;
708 case 8:
709 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
710 bitmap->num_grays = 256;
711 break;
712 }
713
714 slot->format = FT_GLYPH_FORMAT_BITMAP;
715 slot->bitmap_left = glyph.bbx.x_offset;
716 slot->bitmap_top = glyph.bbx.ascent;
717
718 slot->metrics.horiAdvance = glyph.dwidth << 6;
719 slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
720 slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
721 slot->metrics.width = bitmap->width << 6;
722 slot->metrics.height = bitmap->rows << 6;
723
724 /*
725 * XXX DWIDTH1 and VVECTOR should be parsed and
726 * used here, provided such fonts do exist.
727 */
728 ft_synthesize_vertical_metrics( &slot->metrics,
729 bdf->bdffont->bbx.height << 6 );
730
731 Exit:
732 return error;
733 }
734
735
736 /*
737 *
738 * BDF SERVICE
739 *
740 */
741
742 static FT_Error
743 bdf_get_bdf_property( BDF_Face face,
744 const char* prop_name,
745 BDF_PropertyRec *aproperty )
746 {
747 bdf_property_t* prop;
748
749
750 FT_ASSERT( face && face->bdffont );
751
752 prop = bdf_get_font_property( face->bdffont, prop_name );
753 if ( prop )
754 {
755 switch ( prop->format )
756 {
757 case BDF_ATOM:
758 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
759 aproperty->u.atom = prop->value.atom;
760 break;
761
762 case BDF_INTEGER:
763 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
764 {
765 FT_TRACE1(( "bdf_get_bdf_property:"
766 " too large integer 0x%x is truncated\n" ));
767 }
768 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
769 aproperty->u.integer = (FT_Int32)prop->value.l;
770 break;
771
772 case BDF_CARDINAL:
773 if ( prop->value.ul > 0xFFFFFFFFUL )
774 {
775 FT_TRACE1(( "bdf_get_bdf_property:"
776 " too large cardinal 0x%x is truncated\n" ));
777 }
778 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
779 aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
780 break;
781
782 default:
783 goto Fail;
784 }
785 return 0;
786 }
787
788 Fail:
789 return FT_THROW( Invalid_Argument );
790 }
791
792
793 static FT_Error
794 bdf_get_charset_id( BDF_Face face,
795 const char* *acharset_encoding,
796 const char* *acharset_registry )
797 {
798 *acharset_encoding = face->charset_encoding;
799 *acharset_registry = face->charset_registry;
800
801 return 0;
802 }
803
804
805 static const FT_Service_BDFRec bdf_service_bdf =
806 {
807 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
808 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
809 };
810
811
812 /*
813 *
814 * SERVICES LIST
815 *
816 */
817
818 static const FT_ServiceDescRec bdf_services[] =
819 {
820 { FT_SERVICE_ID_BDF, &bdf_service_bdf },
821 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
822 { NULL, NULL }
823 };
824
825
826 FT_CALLBACK_DEF( FT_Module_Interface )
827 bdf_driver_requester( FT_Module module,
828 const char* name )
829 {
830 FT_UNUSED( module );
831
832 return ft_service_list_lookup( bdf_services, name );
833 }
834
835
836
837 FT_CALLBACK_TABLE_DEF
838 const FT_Driver_ClassRec bdf_driver_class =
839 {
840 {
841 FT_MODULE_FONT_DRIVER |
842 FT_MODULE_DRIVER_NO_OUTLINES,
843 sizeof ( FT_DriverRec ),
844
845 "bdf",
846 0x10000L,
847 0x20000L,
848
849 0,
850
851 0, /* FT_Module_Constructor */
852 0, /* FT_Module_Destructor */
853 bdf_driver_requester
854 },
855
856 sizeof ( BDF_FaceRec ),
857 sizeof ( FT_SizeRec ),
858 sizeof ( FT_GlyphSlotRec ),
859
860 BDF_Face_Init,
861 BDF_Face_Done,
862 0, /* FT_Size_InitFunc */
863 0, /* FT_Size_DoneFunc */
864 0, /* FT_Slot_InitFunc */
865 0, /* FT_Slot_DoneFunc */
866
867 BDF_Glyph_Load,
868
869 0, /* FT_Face_GetKerningFunc */
870 0, /* FT_Face_AttachFunc */
871 0, /* FT_Face_GetAdvancesFunc */
872
873 BDF_Size_Request,
874 BDF_Size_Select
875 };
876
877
878 /* END */