sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
bdfdrivr.c
1/* bdfdrivr.c
2
3 FreeType font driver for bdf files
4
5 Copyright (C) 2001-2008, 2011, 2013, 2014 by
6 Francesco Zappa Nardelli
7
8Permission is hereby granted, free of charge, to any person obtaining a copy
9of this software and associated documentation files (the "Software"), to deal
10in the Software without restriction, including without limitation the rights
11to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12copies of the Software, and to permit persons to whom the Software is
13furnished to do so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in
16all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24THE SOFTWARE.
25*/
26
27
31#include <freetype/ftbdf.h>
32#include <freetype/ttnameid.h>
33
36
37#include "bdf.h"
38#include "bdfdrivr.h"
39
40#include "bdferror.h"
41
42
43 /**************************************************************************
44 *
45 * The macro FT_COMPONENT is used in trace mode. It is an implicit
46 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
47 * messages during execution.
48 */
49#undef FT_COMPONENT
50#define FT_COMPONENT bdfdriver
51
52
53 typedef struct BDF_CMapRec_
54 {
55 FT_CMapRec cmap;
56 FT_ULong num_encodings; /* ftobjs.h: FT_CMap->clazz->size */
57 BDF_encoding_el* encodings;
58
59 } BDF_CMapRec, *BDF_CMap;
60
61
62 FT_CALLBACK_DEF( FT_Error )
63 bdf_cmap_init( FT_CMap bdfcmap,
64 FT_Pointer init_data )
65 {
66 BDF_CMap cmap = (BDF_CMap)bdfcmap;
67 BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap );
68 FT_UNUSED( init_data );
69
70
71 cmap->num_encodings = face->bdffont->glyphs_used;
72 cmap->encodings = face->en_table;
73
74 return FT_Err_Ok;
75 }
76
77
78 FT_CALLBACK_DEF( void )
79 bdf_cmap_done( FT_CMap bdfcmap )
80 {
81 BDF_CMap cmap = (BDF_CMap)bdfcmap;
82
83
84 cmap->encodings = NULL;
85 cmap->num_encodings = 0;
86 }
87
88
89 FT_CALLBACK_DEF( FT_UInt )
90 bdf_cmap_char_index( FT_CMap bdfcmap,
91 FT_UInt32 charcode )
92 {
93 BDF_CMap cmap = (BDF_CMap)bdfcmap;
94 BDF_encoding_el* encodings = cmap->encodings;
95 FT_UShort result = 0; /* encodings->glyph */
96
97 FT_ULong min = 0;
98 FT_ULong max = cmap->num_encodings;
99 FT_ULong mid = ( min + max ) >> 1;
100
101
102 while ( min < max )
103 {
104 FT_ULong code = encodings[mid].enc;
105
106
107 if ( charcode == code )
108 {
109 /* increase glyph index by 1 -- */
110 /* we reserve slot 0 for the undefined glyph */
111 result = encodings[mid].glyph + 1;
112 break;
113 }
114
115 if ( charcode < code )
116 max = mid;
117 else
118 min = mid + 1;
119
120 /* reasonable prediction in a continuous block */
121 mid += charcode - code;
122 if ( mid >= max || mid < min )
123 mid = ( min + max ) >> 1;
124 }
125
126 return result;
127 }
128
129
130 FT_CALLBACK_DEF( FT_UInt )
131 bdf_cmap_char_next( FT_CMap bdfcmap,
132 FT_UInt32 *acharcode )
133 {
134 BDF_CMap cmap = (BDF_CMap)bdfcmap;
135 BDF_encoding_el* encodings = cmap->encodings;
136 FT_UShort result = 0; /* encodings->glyph */
137 FT_ULong charcode = *acharcode + 1;
138
139 FT_ULong min = 0;
140 FT_ULong max = cmap->num_encodings;
141 FT_ULong mid = ( min + max ) >> 1;
142
143
144 while ( min < max )
145 {
146 FT_ULong code = encodings[mid].enc;
147
148
149 if ( charcode == code )
150 {
151 /* increase glyph index by 1 -- */
152 /* we reserve slot 0 for the undefined glyph */
153 result = encodings[mid].glyph + 1;
154 goto Exit;
155 }
156
157 if ( charcode < code )
158 max = mid;
159 else
160 min = mid + 1;
161
162 /* prediction in a continuous block */
163 mid += charcode - code;
164 if ( mid >= max || mid < min )
165 mid = ( min + max ) >> 1;
166 }
167
168 charcode = 0;
169 if ( min < cmap->num_encodings )
170 {
171 charcode = encodings[min].enc;
172 result = encodings[min].glyph + 1;
173 }
174
175 Exit:
176 if ( charcode > 0xFFFFFFFFUL )
177 {
178 FT_TRACE1(( "bdf_cmap_char_next: charcode 0x%lx > 32bit API",
179 charcode ));
180 *acharcode = 0;
181 /* XXX: result should be changed to indicate an overflow error */
182 }
183 else
184 *acharcode = (FT_UInt32)charcode;
185 return result;
186 }
187
188
189 static
190 const FT_CMap_ClassRec bdf_cmap_class =
191 {
192 sizeof ( BDF_CMapRec ),
193 bdf_cmap_init,
194 bdf_cmap_done,
195 bdf_cmap_char_index,
196 bdf_cmap_char_next,
197
198 NULL, NULL, NULL, NULL, NULL
199 };
200
201
202 static FT_Error
203 bdf_interpret_style( BDF_Face bdf )
204 {
205 FT_Error error = FT_Err_Ok;
206 FT_Face face = FT_FACE( bdf );
207 FT_Memory memory = face->memory;
208 bdf_font_t* font = bdf->bdffont;
209 bdf_property_t* prop;
210
211 const char* strings[4] = { NULL, NULL, NULL, NULL };
212 size_t lengths[4], nn, len;
213
214
215 face->style_flags = 0;
216
217 prop = bdf_get_font_property( font, "SLANT" );
218 if ( prop && prop->format == BDF_ATOM &&
219 prop->value.atom &&
220 ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
221 *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
222 {
223 face->style_flags |= FT_STYLE_FLAG_ITALIC;
224 strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
225 ? "Oblique"
226 : "Italic";
227 }
228
229 prop = bdf_get_font_property( font, "WEIGHT_NAME" );
230 if ( prop && prop->format == BDF_ATOM &&
231 prop->value.atom &&
232 ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
233 {
234 face->style_flags |= FT_STYLE_FLAG_BOLD;
235 strings[1] = "Bold";
236 }
237
238 prop = bdf_get_font_property( font, "SETWIDTH_NAME" );
239 if ( prop && prop->format == BDF_ATOM &&
240 prop->value.atom && *(prop->value.atom) &&
241 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
242 strings[3] = (const char *)(prop->value.atom);
243
244 prop = bdf_get_font_property( font, "ADD_STYLE_NAME" );
245 if ( prop && prop->format == BDF_ATOM &&
246 prop->value.atom && *(prop->value.atom) &&
247 !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
248 strings[0] = (const char *)(prop->value.atom);
249
250 for ( len = 0, nn = 0; nn < 4; nn++ )
251 {
252 lengths[nn] = 0;
253 if ( strings[nn] )
254 {
255 lengths[nn] = ft_strlen( strings[nn] );
256 len += lengths[nn] + 1;
257 }
258 }
259
260 if ( len == 0 )
261 {
262 strings[0] = "Regular";
263 lengths[0] = ft_strlen( strings[0] );
264 len = lengths[0] + 1;
265 }
266
267 {
268 char* s;
269
270
271 if ( FT_QALLOC( face->style_name, len ) )
272 return error;
273
274 s = face->style_name;
275
276 for ( nn = 0; nn < 4; nn++ )
277 {
278 const char* src = strings[nn];
279
280
281 len = lengths[nn];
282
283 if ( !src )
284 continue;
285
286 /* separate elements with a space */
287 if ( s != face->style_name )
288 *s++ = ' ';
289
290 ft_memcpy( s, src, len );
291
292 /* need to convert spaces to dashes for */
293 /* add_style_name and setwidth_name */
294 if ( nn == 0 || nn == 3 )
295 {
296 size_t mm;
297
298
299 for ( mm = 0; mm < len; mm++ )
300 if ( s[mm] == ' ' )
301 s[mm] = '-';
302 }
303
304 s += len;
305 }
306 *s = 0;
307 }
308
309 return error;
310 }
311
312
313 FT_CALLBACK_DEF( void )
314 BDF_Face_Done( FT_Face face ) /* BDF_Face */
315 {
316 BDF_Face bdfface = (BDF_Face)face;
317 FT_Memory memory;
318
319
320 if ( !face )
321 return;
322
323 memory = FT_FACE_MEMORY( face );
324
325 bdf_free_font( bdfface->bdffont );
326
327 FT_FREE( bdfface->en_table );
328
329 FT_FREE( bdfface->charset_encoding );
330 FT_FREE( bdfface->charset_registry );
331 FT_FREE( face->family_name );
332 FT_FREE( face->style_name );
333
334 FT_FREE( face->available_sizes );
335
336 FT_FREE( bdfface->bdffont );
337 }
338
339
340 FT_CALLBACK_DEF( FT_Error )
341 BDF_Face_Init( FT_Stream stream,
342 FT_Face face, /* BDF_Face */
343 FT_Int face_index,
344 FT_Int num_params,
345 FT_Parameter* params )
346 {
347 FT_Error error = FT_Err_Ok;
348 BDF_Face bdfface = (BDF_Face)face;
349 FT_Memory memory = FT_FACE_MEMORY( face );
350
351 bdf_font_t* font = NULL;
352
353 FT_UNUSED( num_params );
354 FT_UNUSED( params );
355
356
357 FT_TRACE2(( "BDF driver\n" ));
358
359 if ( FT_STREAM_SEEK( 0 ) )
360 goto Exit;
361
362 error = bdf_load_font( stream, memory,
363 BDF_CORRECT_METRICS | BDF_KEEP_UNENCODED, &font );
364 if ( FT_ERR_EQ( error, Missing_Startfont_Field ) )
365 {
366 FT_TRACE2(( " not a BDF file\n" ));
367 goto Fail;
368 }
369 else if ( error )
370 goto Exit;
371
372 /* we have a bdf font: let's construct the face object */
373 bdfface->bdffont = font;
374
375 /* BDF cannot have multiple faces in a single font file.
376 * XXX: non-zero face_index is already invalid argument, but
377 * Type1, Type42 driver has a convention to return
378 * an invalid argument error when the font could be
379 * opened by the specified driver.
380 */
381 if ( face_index > 0 && ( face_index & 0xFFFF ) > 0 )
382 {
383 FT_ERROR(( "BDF_Face_Init: invalid face index\n" ));
384 BDF_Face_Done( face );
385 return FT_THROW( Invalid_Argument );
386 }
387
388 {
389 bdf_property_t* prop = NULL;
390
391
392 FT_TRACE4(( " number of glyphs: allocated %lu (used %lu)\n",
393 font->glyphs_size,
394 font->glyphs_used ));
395 FT_TRACE4(( " number of unencoded glyphs: allocated %lu (used %lu)\n",
396 font->unencoded_size,
397 font->unencoded_used ));
398
399 face->num_faces = 1;
400 face->face_index = 0;
401
402 face->face_flags |= FT_FACE_FLAG_FIXED_SIZES |
403 FT_FACE_FLAG_HORIZONTAL;
404
405 prop = bdf_get_font_property( font, "SPACING" );
406 if ( prop && prop->value.atom )
407 {
408 if ( prop->value.atom[0] == 'p' || prop->value.atom[0] == 'P' )
409 font->spacing = BDF_PROPORTIONAL;
410 else if ( prop->value.atom[0] == 'm' || prop->value.atom[0] == 'M' )
411 font->spacing = BDF_MONOWIDTH;
412 else if ( prop->value.atom[0] == 'c' || prop->value.atom[0] == 'C' )
413 font->spacing = BDF_CHARCELL;
414 }
415
416 if ( font->spacing == BDF_MONOWIDTH ||
417 font->spacing == BDF_CHARCELL )
418 face->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
419
420 /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
421 /* FZ XXX: I need a font to implement this */
422
423 prop = bdf_get_font_property( font, "FAMILY_NAME" );
424 if ( prop && prop->value.atom )
425 {
426 if ( FT_STRDUP( face->family_name, prop->value.atom ) )
427 goto Exit;
428 }
429 else
430 face->family_name = NULL;
431
432 if ( FT_SET_ERROR( bdf_interpret_style( bdfface ) ) )
433 goto Exit;
434
435 /* the number of glyphs (with one slot for the undefined glyph */
436 /* at position 0 and all unencoded glyphs) */
437 face->num_glyphs = (FT_Long)( font->glyphs_size + 1 );
438
439 face->num_fixed_sizes = 1;
440 if ( FT_NEW( face->available_sizes ) )
441 goto Exit;
442
443 {
444 FT_Bitmap_Size* bsize = face->available_sizes;
445 FT_Short resolution_x = 0;
446 FT_Short resolution_y = 0;
447 long value;
448
449
450 prop = bdf_get_font_property( font, "FONT_ASCENT" );
451 if ( prop )
452 font->font_ascent = prop->value.l;
453 else
454 font->font_ascent = font->bbx.ascent;
455 if ( font->font_ascent > 0x7FFF )
456 font->font_ascent = 0x7FFF;
457 else if ( font->font_ascent < 0 )
458 font->font_ascent = 0;
459
460 prop = bdf_get_font_property( font, "FONT_DESCENT" );
461 if ( prop )
462 font->font_descent = prop->value.l;
463 else
464 font->font_descent = font->bbx.descent;
465 if ( font->font_descent > 0x7FFF )
466 font->font_descent = 0x7FFF;
467 else if ( font->font_descent < 0 )
468 font->font_descent = 0;
469
470 bsize->height = (FT_Short)( font->font_ascent + font->font_descent );
471
472 prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
473 if ( prop )
474 {
475#ifdef FT_DEBUG_LEVEL_TRACE
476 if ( prop->value.l < 0 )
477 FT_TRACE0(( "BDF_Face_Init: negative average width\n" ));
478#endif
479 if ( prop->value.l > 0x7FFFL * 10 - 5 ||
480 prop->value.l < -( 0x7FFFL * 10 - 5 ) )
481 {
482 bsize->width = 0x7FFF;
483 FT_TRACE0(( "BDF_Face_Init: clamping average width to value %d\n",
484 bsize->width ));
485 }
486 else
487 bsize->width = FT_ABS( (FT_Short)( ( prop->value.l + 5 ) / 10 ) );
488 }
489 else
490 {
491 /* this is a heuristical value */
492 bsize->width = ( bsize->height * 2 + 1 ) / 3;
493 }
494
495 prop = bdf_get_font_property( font, "POINT_SIZE" );
496 if ( prop )
497 {
498#ifdef FT_DEBUG_LEVEL_TRACE
499 if ( prop->value.l < 0 )
500 FT_TRACE0(( "BDF_Face_Init: negative point size\n" ));
501#endif
502 /* convert from 722.7 decipoints to 72 points per inch */
503 if ( prop->value.l > 0x504C2L || /* 0x7FFF * 72270/7200 */
504 prop->value.l < -0x504C2L )
505 {
506 bsize->size = 0x7FFF;
507 FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
508 bsize->size ));
509 }
510 else
511 bsize->size = FT_MulDiv( FT_ABS( prop->value.l ),
512 64 * 7200,
513 72270L );
514 }
515 else if ( font->point_size )
516 {
517 if ( font->point_size > 0x7FFF )
518 {
519 bsize->size = 0x7FFF;
520 FT_TRACE0(( "BDF_Face_Init: clamping point size to value %ld\n",
521 bsize->size ));
522 }
523 else
524 bsize->size = (FT_Pos)font->point_size << 6;
525 }
526 else
527 {
528 /* this is a heuristical value */
529 bsize->size = bsize->width * 64;
530 }
531
532 prop = bdf_get_font_property( font, "PIXEL_SIZE" );
533 if ( prop )
534 {
535#ifdef FT_DEBUG_LEVEL_TRACE
536 if ( prop->value.l < 0 )
537 FT_TRACE0(( "BDF_Face_Init: negative pixel size\n" ));
538#endif
539 if ( prop->value.l > 0x7FFF || prop->value.l < -0x7FFF )
540 {
541 bsize->y_ppem = 0x7FFF << 6;
542 FT_TRACE0(( "BDF_Face_Init: clamping pixel size to value %ld\n",
543 bsize->y_ppem ));
544 }
545 else
546 bsize->y_ppem = FT_ABS( (FT_Short)prop->value.l ) << 6;
547 }
548
549 prop = bdf_get_font_property( font, "RESOLUTION_X" );
550 if ( prop )
551 value = prop->value.l;
552 else
553 value = (long)font->resolution_x;
554 if ( value )
555 {
556#ifdef FT_DEBUG_LEVEL_TRACE
557 if ( value < 0 )
558 FT_TRACE0(( "BDF_Face_Init: negative X resolution\n" ));
559#endif
560 if ( value > 0x7FFF || value < -0x7FFF )
561 {
562 resolution_x = 0x7FFF;
563 FT_TRACE0(( "BDF_Face_Init: clamping X resolution to value %d\n",
564 resolution_x ));
565 }
566 else
567 resolution_x = FT_ABS( (FT_Short)value );
568 }
569
570 prop = bdf_get_font_property( font, "RESOLUTION_Y" );
571 if ( prop )
572 value = prop->value.l;
573 else
574 value = (long)font->resolution_y;
575 if ( value )
576 {
577#ifdef FT_DEBUG_LEVEL_TRACE
578 if ( value < 0 )
579 FT_TRACE0(( "BDF_Face_Init: negative Y resolution\n" ));
580#endif
581 if ( value > 0x7FFF || value < -0x7FFF )
582 {
583 resolution_y = 0x7FFF;
584 FT_TRACE0(( "BDF_Face_Init: clamping Y resolution to value %d\n",
585 resolution_y ));
586 }
587 else
588 resolution_y = FT_ABS( (FT_Short)value );
589 }
590
591 if ( bsize->y_ppem == 0 )
592 {
593 bsize->y_ppem = bsize->size;
594 if ( resolution_y )
595 bsize->y_ppem = FT_MulDiv( bsize->y_ppem, resolution_y, 72 );
596 }
597 if ( resolution_x && resolution_y )
598 bsize->x_ppem = FT_MulDiv( bsize->y_ppem,
599 resolution_x,
600 resolution_y );
601 else
602 bsize->x_ppem = bsize->y_ppem;
603
604 prop = bdf_get_font_property( font, "DEFAULT_CHAR" );
605 if ( prop )
606 font->default_char = prop->value.ul;
607 else
608 font->default_char = ~0UL;
609 }
610
611 /* encoding table */
612 {
613 bdf_glyph_t* cur = font->glyphs;
614 unsigned long n;
615
616
617 if ( FT_QNEW_ARRAY( bdfface->en_table, font->glyphs_size ) )
618 goto Exit;
619
620 bdfface->default_glyph = 0;
621 for ( n = 0; n < font->glyphs_size; n++ )
622 {
623 (bdfface->en_table[n]).enc = cur[n].encoding;
624 FT_TRACE4(( " idx %lu, val 0x%lX\n", n, cur[n].encoding ));
625 (bdfface->en_table[n]).glyph = (FT_UShort)n;
626
627 if ( cur[n].encoding == font->default_char )
628 {
629 if ( n < FT_UINT_MAX )
630 bdfface->default_glyph = (FT_UInt)n;
631 else
632 FT_TRACE1(( "BDF_Face_Init:"
633 " idx %lu is too large for this system\n", n ));
634 }
635 }
636 }
637
638 /* charmaps */
639 {
640 bdf_property_t *charset_registry, *charset_encoding;
641 FT_Bool unicode_charmap = 0;
642
643
644 charset_registry =
645 bdf_get_font_property( font, "CHARSET_REGISTRY" );
646 charset_encoding =
647 bdf_get_font_property( font, "CHARSET_ENCODING" );
648 if ( charset_registry && charset_encoding )
649 {
650 if ( charset_registry->format == BDF_ATOM &&
651 charset_encoding->format == BDF_ATOM &&
652 charset_registry->value.atom &&
653 charset_encoding->value.atom )
654 {
655 const char* s;
656
657
658 if ( FT_STRDUP( bdfface->charset_encoding,
659 charset_encoding->value.atom ) ||
660 FT_STRDUP( bdfface->charset_registry,
661 charset_registry->value.atom ) )
662 goto Exit;
663
664 /* Uh, oh, compare first letters manually to avoid dependency */
665 /* on locales. */
666 s = bdfface->charset_registry;
667 if ( ( s[0] == 'i' || s[0] == 'I' ) &&
668 ( s[1] == 's' || s[1] == 'S' ) &&
669 ( s[2] == 'o' || s[2] == 'O' ) )
670 {
671 s += 3;
672 if ( !ft_strcmp( s, "10646" ) ||
673 ( !ft_strcmp( s, "8859" ) &&
674 !ft_strcmp( bdfface->charset_encoding, "1" ) ) )
675 unicode_charmap = 1;
676 /* another name for ASCII */
677 else if ( !ft_strcmp( s, "646.1991" ) &&
678 !ft_strcmp( bdfface->charset_encoding, "IRV" ) )
679 unicode_charmap = 1;
680 }
681
682 {
683 FT_CharMapRec charmap;
684
685
686 charmap.face = face;
687 charmap.encoding = FT_ENCODING_NONE;
688 /* initial platform/encoding should indicate unset status? */
689 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
690 charmap.encoding_id = TT_APPLE_ID_DEFAULT;
691
692 if ( unicode_charmap )
693 {
694 charmap.encoding = FT_ENCODING_UNICODE;
695 charmap.platform_id = TT_PLATFORM_MICROSOFT;
696 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
697 }
698
699 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
700 }
701
702 goto Exit;
703 }
704 }
705
706 /* otherwise assume Adobe standard encoding */
707
708 {
709 FT_CharMapRec charmap;
710
711
712 charmap.face = face;
713 charmap.encoding = FT_ENCODING_ADOBE_STANDARD;
714 charmap.platform_id = TT_PLATFORM_ADOBE;
715 charmap.encoding_id = TT_ADOBE_ID_STANDARD;
716
717 error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL );
718
719 /* Select default charmap */
720 if ( face->num_charmaps )
721 face->charmap = face->charmaps[0];
722 }
723 }
724 }
725
726 Exit:
727 return error;
728
729 Fail:
730 BDF_Face_Done( face );
731 return FT_THROW( Unknown_File_Format );
732 }
733
734
735 FT_CALLBACK_DEF( FT_Error )
736 BDF_Size_Select( FT_Size size,
737 FT_ULong strike_index )
738 {
739 bdf_font_t* bdffont = ( (BDF_Face)size->face )->bdffont;
740
741
742 FT_Select_Metrics( size->face, strike_index );
743
744 size->metrics.ascender = bdffont->font_ascent * 64;
745 size->metrics.descender = -bdffont->font_descent * 64;
746 size->metrics.max_advance = bdffont->bbx.width * 64;
747
748 return FT_Err_Ok;
749 }
750
751
752 FT_CALLBACK_DEF( FT_Error )
753 BDF_Size_Request( FT_Size size,
754 FT_Size_Request req )
755 {
756 FT_Face face = size->face;
757 FT_Bitmap_Size* bsize = face->available_sizes;
758 bdf_font_t* bdffont = ( (BDF_Face)face )->bdffont;
759 FT_Error error = FT_ERR( Invalid_Pixel_Size );
760 FT_Long height;
761
762
763 height = FT_REQUEST_HEIGHT( req );
764 height = ( height + 32 ) >> 6;
765
766 switch ( req->type )
767 {
768 case FT_SIZE_REQUEST_TYPE_NOMINAL:
769 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
770 error = FT_Err_Ok;
771 break;
772
773 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
774 if ( height == ( bdffont->font_ascent +
775 bdffont->font_descent ) )
776 error = FT_Err_Ok;
777 break;
778
779 default:
780 error = FT_THROW( Unimplemented_Feature );
781 break;
782 }
783
784 if ( error )
785 return error;
786 else
787 return BDF_Size_Select( size, 0 );
788 }
789
790
791
792 FT_CALLBACK_DEF( FT_Error )
793 BDF_Glyph_Load( FT_GlyphSlot slot,
794 FT_Size size,
795 FT_UInt glyph_index,
796 FT_Int32 load_flags )
797 {
798 FT_Face face = size->face;
799 BDF_Face bdf = (BDF_Face)face;
800 FT_Error error = FT_Err_Ok;
801 FT_Bitmap* bitmap = &slot->bitmap;
802 bdf_glyph_t glyph;
803 int bpp = bdf->bdffont->bpp;
804
805 FT_UNUSED( load_flags );
806
807
808 if ( !face )
809 {
810 error = FT_THROW( Invalid_Face_Handle );
811 goto Exit;
812 }
813
814 if ( glyph_index >= (FT_UInt)face->num_glyphs )
815 {
816 error = FT_THROW( Invalid_Argument );
817 goto Exit;
818 }
819
820 FT_TRACE1(( "BDF_Glyph_Load: glyph index %u\n", glyph_index ));
821
822 /* index 0 is the undefined glyph */
823 if ( glyph_index == 0 )
824 glyph_index = bdf->default_glyph;
825 else
826 glyph_index--;
827
828 /* slot, bitmap => freetype, glyph => bdflib */
829 glyph = bdf->bdffont->glyphs[glyph_index];
830
831 bitmap->rows = glyph.bbx.height;
832 bitmap->width = glyph.bbx.width;
833 if ( glyph.bpr > FT_INT_MAX )
834 FT_TRACE1(( "BDF_Glyph_Load: too large pitch %lu is truncated\n",
835 glyph.bpr ));
836 bitmap->pitch = (int)glyph.bpr; /* same as FT_Bitmap.pitch */
837
838 /* note: we don't allocate a new array to hold the bitmap; */
839 /* we can simply point to it */
840 ft_glyphslot_set_bitmap( slot, glyph.bitmap );
841
842 switch ( bpp )
843 {
844 case 1:
845 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
846 break;
847 case 2:
848 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY2;
849 break;
850 case 4:
851 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY4;
852 break;
853 case 8:
854 bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
855 bitmap->num_grays = 256;
856 break;
857 }
858
859 slot->format = FT_GLYPH_FORMAT_BITMAP;
860 slot->bitmap_left = glyph.bbx.x_offset;
861 slot->bitmap_top = glyph.bbx.ascent;
862
863 slot->metrics.horiAdvance = (FT_Pos)( glyph.dwidth * 64 );
864 slot->metrics.horiBearingX = (FT_Pos)( glyph.bbx.x_offset * 64 );
865 slot->metrics.horiBearingY = (FT_Pos)( glyph.bbx.ascent * 64 );
866 slot->metrics.width = (FT_Pos)( bitmap->width * 64 );
867 slot->metrics.height = (FT_Pos)( bitmap->rows * 64 );
868
869 /*
870 * XXX DWIDTH1 and VVECTOR should be parsed and
871 * used here, provided such fonts do exist.
872 */
873 ft_synthesize_vertical_metrics( &slot->metrics,
874 bdf->bdffont->bbx.height * 64 );
875
876 Exit:
877 return error;
878 }
879
880
881 /*
882 *
883 * BDF SERVICE
884 *
885 */
886
887 FT_CALLBACK_DEF( FT_Error )
888 bdf_get_bdf_property( FT_Face face, /* BDF_Face */
889 const char* prop_name,
890 BDF_PropertyRec *aproperty )
891 {
892 BDF_Face bdfface = (BDF_Face)face;
893 bdf_property_t* prop;
894
895
896 FT_ASSERT( bdfface && bdfface->bdffont );
897
898 prop = bdf_get_font_property( bdfface->bdffont, prop_name );
899 if ( prop )
900 {
901 switch ( prop->format )
902 {
903 case BDF_ATOM:
904 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
905 aproperty->u.atom = prop->value.atom;
906 break;
907
908 case BDF_INTEGER:
909 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
910 {
911 FT_TRACE1(( "bdf_get_bdf_property:"
912 " too large integer 0x%lx is truncated\n",
913 prop->value.l ));
914 }
915 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
916 aproperty->u.integer = (FT_Int32)prop->value.l;
917 break;
918
919 case BDF_CARDINAL:
920 if ( prop->value.ul > 0xFFFFFFFFUL )
921 {
922 FT_TRACE1(( "bdf_get_bdf_property:"
923 " too large cardinal 0x%lx is truncated\n",
924 prop->value.ul ));
925 }
926 aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
927 aproperty->u.cardinal = (FT_UInt32)prop->value.ul;
928 break;
929
930 default:
931 goto Fail;
932 }
933 return 0;
934 }
935
936 Fail:
937 return FT_THROW( Invalid_Argument );
938 }
939
940
941 FT_CALLBACK_DEF( FT_Error )
942 bdf_get_charset_id( FT_Face face, /* BDF_Face */
943 const char* *acharset_encoding,
944 const char* *acharset_registry )
945 {
946 BDF_Face bdfface = (BDF_Face)face;
947
948
949 *acharset_encoding = bdfface->charset_encoding;
950 *acharset_registry = bdfface->charset_registry;
951
952 return 0;
953 }
954
955
956 static const FT_Service_BDFRec bdf_service_bdf =
957 {
958 (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id, /* get_charset_id */
959 (FT_BDF_GetPropertyFunc) bdf_get_bdf_property /* get_property */
960 };
961
962
963 /*
964 *
965 * SERVICES LIST
966 *
967 */
968
969 static const FT_ServiceDescRec bdf_services[] =
970 {
971 { FT_SERVICE_ID_BDF, &bdf_service_bdf },
972 { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_BDF },
973 { NULL, NULL }
974 };
975
976
977 FT_CALLBACK_DEF( FT_Module_Interface )
978 bdf_driver_requester( FT_Module module,
979 const char* name )
980 {
981 FT_UNUSED( module );
982
983 return ft_service_list_lookup( bdf_services, name );
984 }
985
986
987 FT_CALLBACK_TABLE_DEF
988 const FT_Driver_ClassRec bdf_driver_class =
989 {
990 {
991 FT_MODULE_FONT_DRIVER |
992 FT_MODULE_DRIVER_NO_OUTLINES,
993 sizeof ( FT_DriverRec ),
994
995 "bdf",
996 0x10000L,
997 0x20000L,
998
999 NULL, /* module-specific interface */
1000
1001 NULL, /* FT_Module_Constructor module_init */
1002 NULL, /* FT_Module_Destructor module_done */
1003 bdf_driver_requester /* FT_Module_Requester get_interface */
1004 },
1005
1006 sizeof ( BDF_FaceRec ),
1007 sizeof ( FT_SizeRec ),
1008 sizeof ( FT_GlyphSlotRec ),
1009
1010 BDF_Face_Init, /* FT_Face_InitFunc init_face */
1011 BDF_Face_Done, /* FT_Face_DoneFunc done_face */
1012 NULL, /* FT_Size_InitFunc init_size */
1013 NULL, /* FT_Size_DoneFunc done_size */
1014 NULL, /* FT_Slot_InitFunc init_slot */
1015 NULL, /* FT_Slot_DoneFunc done_slot */
1016
1017 BDF_Glyph_Load, /* FT_Slot_LoadFunc load_glyph */
1018
1019 NULL, /* FT_Face_GetKerningFunc get_kerning */
1020 NULL, /* FT_Face_AttachFunc attach_file */
1021 NULL, /* FT_Face_GetAdvancesFunc get_advances */
1022
1023 BDF_Size_Request, /* FT_Size_RequestFunc request_size */
1024 BDF_Size_Select /* FT_Size_SelectFunc select_size */
1025 };
1026
1027
1028/* END */