|
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 */ |