caa142b5ef428b7ce2b1566bb4ec5d79cdff70fc
[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
355
356 FT_TRACE2(( "BDF driver\n" ));
357
358 if ( FT_STREAM_SEEK( 0 ) )
359 goto Exit;
360
361 options.correct_metrics = 1; /* FZ XXX: options semantics */
362 options.keep_unencoded = 1;
363 options.keep_comments = 0;
364 options.font_spacing = BDF_PROPORTIONAL;
365
366 error = bdf_load_font( stream, memory, &options, &font );
367 if ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
368 {
369 FT_TRACE2(( " not a BDF file\n" ));
370 goto Fail;
371 }
372 else if ( error )
373 goto Exit;
374
375 /* we have a bdf font: let's construct the face object */
376 face->bdffont = font;
377
378 /* BDF could not have multiple face in single font file.
379 * XXX: non-zero face_index is already invalid argument, but
380 * Type1, Type42 driver has a convention to return
381 * an invalid argument error when the font could be
382 * opened by the specified driver.
383 */
384 if ( face_index > 0 ) {
385 FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
386 BDF_Face_Done( bdfface );
387 return FT_THROW( Invalid_Argument );
388 }
389
390 {
391 bdf_property_t* prop = NULL;
392
393
394 FT_TRACE4(( " number of glyphs: allocated %d (used %d)\n",
395 font->glyphs_size,
396 font->glyphs_used ));
397 FT_TRACE4(( " number of unencoded glyphs: allocated %d (used %d)\n",
398 font->unencoded_size,
399 font->unencoded_used ));
400
401 bdfface->num_faces = 1;
402 bdfface->face_index = 0;
403 bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES |
404 FT_FACE_FLAG_HORIZONTAL |
405 FT_FACE_FLAG_FAST_GLYPHS;
406
407 prop = bdf_get_font_property( font, "SPACING" );
408 if ( prop && prop->format == BDF_ATOM &&
409 prop->value.atom &&
410 ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
411 *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
412 bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
413
414 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
415 /* FZ XXX: I need a font to implement this */
416
417 prop = bdf_get_font_property( font, "FAMILY_NAME" );
418 if ( prop && prop->value.atom )
419 {
420 if ( FT_STRDUP( bdfface->family_name, prop->value.atom ) )
421 goto Exit;
422 }
423 else
424 bdfface->family_name = 0;
425
426 if ( ( error = bdf_interpret_style( face ) ) != 0 )
427 goto Exit;
428
429 /* the number of glyphs (with one slot for the undefined glyph */
430 /* at position 0 and all unencoded glyphs) */
431 bdfface->num_glyphs = font->glyphs_size + 1;
432
433 bdfface->num_fixed_sizes = 1;
434 if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
435 goto Exit;
436
437 {
438 FT_Bitmap_Size* bsize = bdfface->available_sizes;
439 FT_Short resolution_x = 0, resolution_y = 0;
440
441
442 FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
443
444 bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
445
446 prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
447 if ( prop )
448 bsize->width = (FT_Short)( ( prop->value.l + 5 ) / 10 );
449 else
450 bsize->width = (FT_Short)( bsize->height * 2/3 );
451
452 prop = bdf_get_font_property( font, "POINT_SIZE" );
453 if ( prop )
454 /* convert from 722.7 decipoints to 72 points per inch */
455 bsize->size =
456 (FT_Pos)( ( prop->value.l * 64 * 7200 + 36135L ) / 72270L );
457 else
458 bsize->size = bsize->width << 6;
459
460 prop = bdf_get_font_property( font, "PIXEL_SIZE" );
461 if ( prop )
462 bsize->y_ppem = (FT_Short)prop->value.l << 6;
463
464 prop = bdf_get_font_property( font, "RESOLUTION_X" );
465 if ( prop )
466 resolution_x = (FT_Short)prop->value.l;
467
468 prop = bdf_get_font_property( font, "RESOLUTION_Y" );
469 if ( prop )
470 resolution_y = (FT_Short)prop->value.l;
471
472 if ( bsize->y_ppem == 0 )
473 {
474 bsize->y_ppem = bsize->size;
475 if ( resolution_y )
476 bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
477 }
478 if ( resolution_x && resolution_y )
479 bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
480 else
481 bsize->x_ppem = bsize->y_ppem;
482 }
483
484 /* encoding table */
485 {
486 bdf_glyph_t* cur = font->glyphs;
487 unsigned long n;
488
489
490 if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
491 goto Exit;
492
493 face->default_glyph = 0;
494 for ( n = 0; n < font->glyphs_size; n++ )
495 {
496 (face->en_table[n]).enc = cur[n].encoding;
497 FT_TRACE4(( " idx %d, val 0x%lX\n", n, cur[n].encoding ));
498 (face->en_table[n]).glyph = (FT_Short)n;
499
500 if ( cur[n].encoding == font->default_char )
501 {
502 if ( n < FT_UINT_MAX )
503 face->default_glyph = (FT_UInt)n;
504 else
505 FT_TRACE1(( "BDF_Face_Init:"
506 " idx %d is too large for this system\n", n ));
507 }
508 }
509 }
510
511 /* charmaps */
512 {
513 bdf_property_t *charset_registry = 0, *charset_encoding = 0;
514 FT_Bool unicode_charmap = 0;
515
516
517 charset_registry =
518 bdf_get_font_property( font, "CHARSET_REGISTRY" );
519 charset_encoding =
520 bdf_get_font_property( font, "CHARSET_ENCODING" );
521 if ( charset_registry && charset_encoding )
522 {
523 if ( charset_registry->format == BDF_ATOM &&
524 charset_encoding->format == BDF_ATOM &&
525 charset_registry->value.atom &&
526 charset_encoding->value.atom )
527 {
528 const char* s;
529
530
531 if ( FT_STRDUP( face->charset_encoding,
532 charset_encoding->value.atom ) ||
533 FT_STRDUP( face->charset_registry,
534 charset_registry->value.atom ) )
535 goto Exit;
536
537 /* Uh, oh, compare first letters manually to avoid dependency */
538 /* on locales. */
539 s = face->charset_registry;
540 if ( ( s[0] == 'i' || s[0] == 'I' ) &&
541 ( s[1] == 's' || s[1] == 'S' ) &&
542 ( s[2] == 'o' || s[2] == 'O' ) )
543 {
544 s += 3;
545 if ( !ft_strcmp( s, "10646" ) ||
546 ( !ft_strcmp( s, "8859" ) &&
547 !ft_strcmp( face->charset_encoding, "1" ) ) )
548 unicode_charmap = 1;
549 }
550
551 {
552 FT_CharMapRec charmap;
553
554
555 charmap.face = FT_FACE( face );
556 charmap.encoding = FT_ENCODING_NONE;
557 /* initial platform/encoding should indicate unset status? */
558 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
559 charmap.encoding_id = TT_APPLE_ID_DEFAULT;
560
561 if ( unicode_charmap )
562 {
563 charmap.encoding = FT_ENCODING_UNICODE;
564 charmap.platform_id = TT_PLATFORM_MICROSOFT;
565 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
566 }
567
568 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
569
570 #if 0
571 /* Select default charmap */
572 if ( bdfface->num_charmaps )
573 bdfface->charmap = bdfface->charmaps[0];
574 #endif
575 }
576
577 goto Exit;
578 }
579 }
580
581 /* otherwise assume Adobe standard encoding */
582
583 {
584 FT_CharMapRec charmap;
585
586
587 charmap.face = FT_FACE( face );
588 charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
589 charmap.platform_id = TT_PLATFORM_ADOBE;
590 charmap.encoding_id = TT_ADOBE_ID_STANDARD;
591
592 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
593
594 /* Select default charmap */
595 if ( bdfface->num_charmaps )
596 bdfface->charmap = bdfface->charmaps[0];
597 }
598 }
599 }
600
601 Exit:
602 return error;
603
604 Fail:
605 BDF_Face_Done( bdfface );
606 return FT_THROW( Unknown_File_Format );
607 }
608
609
610 FT_CALLBACK_DEF( FT_Error )
611 BDF_Size_Select( FT_Size size,
612 FT_ULong strike_index )
613 {
614 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;
615
616
617 FT_Select_Metrics( size->face, strike_index );
618
619 size->metrics.ascender = bdffont->font_ascent << 6;
620 size->metrics.descender = -bdffont->font_descent << 6;
621 size->metrics.max_advance = bdffont->bbx.width << 6;
622
623 return FT_Err_Ok;
624 }
625
626
627 FT_CALLBACK_DEF( FT_Error )
628 BDF_Size_Request( FT_Size size,
629 FT_Size_Request req )
630 {
631 FT_Face face = size->face;
632 FT_Bitmap_Size* bsize = face->available_sizes;
633 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;
634 FT_Error error = FT_ERR( Invalid_Pixel_Size );
635 FT_Long height;
636
637
638 height = FT_REQUEST_HEIGHT( req );
639 height = ( height + 32 ) >> 6;
640
641 switch ( req->type )
642 {
643 case FT_SIZE_REQUEST_TYPE_NOMINAL:
644 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
645 error = FT_Err_Ok;
646 break;
647
648 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
649 if ( height == ( bdffont->font_ascent +
650 bdffont->font_descent ) )
651 error = FT_Err_Ok;
652 break;
653
654 default:
655 error = FT_THROW( Unimplemented_Feature );
656 break;
657 }
658
659 if ( error )
660 return error;
661 else
662 return BDF_Size_Select( size, 0 );
663 }
664
665
666
667 FT_CALLBACK_DEF( FT_Error )
668 BDF_Glyph_Load( FT_GlyphSlot slot,
669 FT_Size size,
670 FT_UInt glyph_index,
671 FT_Int32 load_flags )
672 {
673 BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size );
674 FT_Face face = FT_FACE( bdf );
675 FT_Error error = FT_Err_Ok;
676 FT_Bitmap* bitmap = &slot->bitmap;
677 bdf_glyph_t glyph;
678 int bpp = bdf->bdffont->bpp;
679
680 FT_UNUSED( load_flags );
681
682
683 if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
684 {
685 error = FT_THROW( Invalid_Argument );
686 goto Exit;
687 }
688
689 FT_TRACE1(( "BDF_Glyph_Load: glyph index %d\n", glyph_index ));
690
691 /* index 0 is the undefined glyph */
692 if ( glyph_index == 0 )
693 glyph_index = bdf->default_glyph;
694 else
695 glyph_index--;
696
697 /* slot, bitmap => freetype, glyph => bdflib */
698 glyph = bdf->bdffont->glyphs[glyph_index];
699
700 bitmap->rows = glyph.bbx.height;
701 bitmap->width = glyph.bbx.width;
702 if ( glyph.bpr > INT_MAX )
703 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %d is truncated\n",
704 glyph.bpr ));
705 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
706
707 /* note: we don't allocate a new array to hold the bitmap; */
708 /* we can simply point to it */
709 ft_glyphslot_set_bitmap( slot, glyph.bitmap );
710
711 switch ( bpp )
712 {
713 case 1:
714 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
715 break;
716 case 2:
717 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
718 break;
719 case 4:
720 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
721 break;
722 case 8:
723 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
724 bitmap->num_grays = 256;
725 break;
726 }
727
728 slot->format = FT_GLYPH_FORMAT_BITMAP;
729 slot->bitmap_left = glyph.bbx.x_offset;
730 slot->bitmap_top = glyph.bbx.ascent;
731
732 slot->metrics.horiAdvance = glyph.dwidth << 6;
733 slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
734 slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
735 slot->metrics.width = bitmap->width << 6;
736 slot->metrics.height = bitmap->rows << 6;
737
738 /*
739 * XXX DWIDTH1 and VVECTOR should be parsed and
740 * used here, provided such fonts do exist.
741 */
742 ft_synthesize_vertical_metrics( &slot->metrics,
743 bdf->bdffont->bbx.height << 6 );
744
745 Exit:
746 return error;
747 }
748
749
750 /*
751 *
752 * BDF SERVICE
753 *
754 */
755
756 static FT_Error
757 bdf_get_bdf_property( BDF_Face face,
758 const char* prop_name,
759 BDF_PropertyRec *aproperty )
760 {
761 bdf_property_t* prop;
762
763
764 FT_ASSERT( face && face->bdffont );
765
766 prop = bdf_get_font_property( face->bdffont, prop_name );
767 if ( prop )
768 {
769 switch ( prop->format )
770 {
771 case BDF_ATOM:
772 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
773 aproperty->u.atom = prop->value.atom;
774 break;
775
776 case BDF_INTEGER:
777 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
778 {
779 FT_TRACE1(( "bdf_get_bdf_property:"
780 " too large integer 0x%x is truncated\n" ));
781 }
782 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
783 aproperty->u.integer = (FT_Int32)prop->value.l;
784 break;
785
786 case BDF_CARDINAL:
787 if ( prop->value.ul > 0xFFFFFFFFUL )
788 {
789 FT_TRACE1(( "bdf_get_bdf_property:"
790 " too large cardinal 0x%x is truncated\n" ));
791 }
792 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
793 aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
794 break;
795
796 default:
797 goto Fail;
798 }
799 return 0;
800 }
801
802 Fail:
803 return FT_THROW( Invalid_Argument );
804 }
805
806
807 static FT_Error
808 bdf_get_charset_id( BDF_Face face,
809 const char* *acharset_encoding,
810 const char* *acharset_registry )
811 {
812 *acharset_encoding = face->charset_encoding;
813 *acharset_registry = face->charset_registry;
814
815 return 0;
816 }
817
818
819 static const FT_Service_BDFRec bdf_service_bdf =
820 {
821 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
822 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property
823 };
824
825
826 /*
827 *
828 * SERVICES LIST
829 *
830 */
831
832 static const FT_ServiceDescRec bdf_services[] =
833 {
834 { FT_SERVICE_ID_BDF, &bdf_service_bdf },
835 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
836 { NULL, NULL }
837 };
838
839
840 FT_CALLBACK_DEF( FT_Module_Interface )
841 bdf_driver_requester( FT_Module module,
842 const char* name )
843 {
844 FT_UNUSED( module );
845
846 return ft_service_list_lookup( bdf_services, name );
847 }
848
849
850
851 FT_CALLBACK_TABLE_DEF
852 const FT_Driver_ClassRec bdf_driver_class =
853 {
854 {
855 FT_MODULE_FONT_DRIVER |
856 FT_MODULE_DRIVER_NO_OUTLINES,
857 sizeof ( FT_DriverRec ),
858
859 "bdf",
860 0x10000L,
861 0x20000L,
862
863 0,
864
865 0, /* FT_Module_Constructor */
866 0, /* FT_Module_Destructor */
867 bdf_driver_requester
868 },
869
870 sizeof ( BDF_FaceRec ),
871 sizeof ( FT_SizeRec ),
872 sizeof ( FT_GlyphSlotRec ),
873
874 BDF_Face_Init,
875 BDF_Face_Done,
876 0, /* FT_Size_InitFunc */
877 0, /* FT_Size_DoneFunc */
878 0, /* FT_Slot_InitFunc */
879 0, /* FT_Slot_DoneFunc */
880
881 BDF_Glyph_Load,
882
883 0, /* FT_Face_GetKerningFunc */
884 0, /* FT_Face_AttachFunc */
885 0, /* FT_Face_GetAdvancesFunc */
886
887 BDF_Size_Request,
888 BDF_Size_Select
889 };
890
891
892 /* END */