[CMAKE]
[reactos.git] / lib / 3rdparty / freetype / src / pcf / pcfdrivr.c
1 /* pcfdrivr.c
2
3 FreeType font driver for pcf files
4
5 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 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
28 #include <ft2build.h>
29
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
33 #include FT_GZIP_H
34 #include FT_LZW_H
35 #include FT_ERRORS_H
36 #include FT_BDF_H
37 #include FT_TRUETYPE_IDS_H
38
39 #include "pcf.h"
40 #include "pcfdrivr.h"
41 #include "pcfread.h"
42
43 #include "pcferror.h"
44 #include "pcfutil.h"
45
46 #undef FT_COMPONENT
47 #define FT_COMPONENT trace_pcfread
48
49 #include FT_SERVICE_BDF_H
50 #include FT_SERVICE_XFREE86_NAME_H
51
52
53 /*************************************************************************/
54 /* */
55 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
56 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
57 /* messages during execution. */
58 /* */
59 #undef FT_COMPONENT
60 #define FT_COMPONENT trace_pcfdriver
61
62
63 typedef struct PCF_CMapRec_
64 {
65 FT_CMapRec root;
66 FT_UInt num_encodings;
67 PCF_Encoding encodings;
68
69 } PCF_CMapRec, *PCF_CMap;
70
71
72 FT_CALLBACK_DEF( FT_Error )
73 pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */
74 FT_Pointer init_data )
75 {
76 PCF_CMap cmap = (PCF_CMap)pcfcmap;
77 PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap );
78
79 FT_UNUSED( init_data );
80
81
82 cmap->num_encodings = (FT_UInt)face->nencodings;
83 cmap->encodings = face->encodings;
84
85 return PCF_Err_Ok;
86 }
87
88
89 FT_CALLBACK_DEF( void )
90 pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */
91 {
92 PCF_CMap cmap = (PCF_CMap)pcfcmap;
93
94
95 cmap->encodings = NULL;
96 cmap->num_encodings = 0;
97 }
98
99
100 FT_CALLBACK_DEF( FT_UInt )
101 pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */
102 FT_UInt32 charcode )
103 {
104 PCF_CMap cmap = (PCF_CMap)pcfcmap;
105 PCF_Encoding encodings = cmap->encodings;
106 FT_UInt min, max, mid;
107 FT_UInt result = 0;
108
109
110 min = 0;
111 max = cmap->num_encodings;
112
113 while ( min < max )
114 {
115 FT_ULong code;
116
117
118 mid = ( min + max ) >> 1;
119 code = encodings[mid].enc;
120
121 if ( charcode == code )
122 {
123 result = encodings[mid].glyph + 1;
124 break;
125 }
126
127 if ( charcode < code )
128 max = mid;
129 else
130 min = mid + 1;
131 }
132
133 return result;
134 }
135
136
137 FT_CALLBACK_DEF( FT_UInt )
138 pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */
139 FT_UInt32 *acharcode )
140 {
141 PCF_CMap cmap = (PCF_CMap)pcfcmap;
142 PCF_Encoding encodings = cmap->encodings;
143 FT_UInt min, max, mid;
144 FT_ULong charcode = *acharcode + 1;
145 FT_UInt result = 0;
146
147
148 min = 0;
149 max = cmap->num_encodings;
150
151 while ( min < max )
152 {
153 FT_ULong code;
154
155
156 mid = ( min + max ) >> 1;
157 code = encodings[mid].enc;
158
159 if ( charcode == code )
160 {
161 result = encodings[mid].glyph + 1;
162 goto Exit;
163 }
164
165 if ( charcode < code )
166 max = mid;
167 else
168 min = mid + 1;
169 }
170
171 charcode = 0;
172 if ( min < cmap->num_encodings )
173 {
174 charcode = encodings[min].enc;
175 result = encodings[min].glyph + 1;
176 }
177
178 Exit:
179 if ( charcode > 0xFFFFFFFFUL )
180 {
181 FT_TRACE1(( "pcf_cmap_char_next: charcode 0x%x > 32bit API" ));
182 *acharcode = 0;
183 /* XXX: result should be changed to indicate an overflow error */
184 }
185 else
186 *acharcode = (FT_UInt32)charcode;
187 return result;
188 }
189
190
191 FT_CALLBACK_TABLE_DEF
192 const FT_CMap_ClassRec pcf_cmap_class =
193 {
194 sizeof ( PCF_CMapRec ),
195 pcf_cmap_init,
196 pcf_cmap_done,
197 pcf_cmap_char_index,
198 pcf_cmap_char_next,
199
200 NULL, NULL, NULL, NULL, NULL
201 };
202
203
204 FT_CALLBACK_DEF( void )
205 PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */
206 {
207 PCF_Face face = (PCF_Face)pcfface;
208 FT_Memory memory;
209
210
211 if ( !face )
212 return;
213
214 memory = FT_FACE_MEMORY( face );
215
216 FT_FREE( face->encodings );
217 FT_FREE( face->metrics );
218
219 /* free properties */
220 {
221 PCF_Property prop;
222 FT_Int i;
223
224
225 if ( face->properties )
226 {
227 for ( i = 0; i < face->nprops; i++ )
228 {
229 prop = &face->properties[i];
230
231 if ( prop )
232 {
233 FT_FREE( prop->name );
234 if ( prop->isString )
235 FT_FREE( prop->value.atom );
236 }
237 }
238 }
239 FT_FREE( face->properties );
240 }
241
242 FT_FREE( face->toc.tables );
243 FT_FREE( pcfface->family_name );
244 FT_FREE( pcfface->style_name );
245 FT_FREE( pcfface->available_sizes );
246 FT_FREE( face->charset_encoding );
247 FT_FREE( face->charset_registry );
248
249 FT_TRACE4(( "PCF_Face_Done: done face\n" ));
250
251 /* close gzip/LZW stream if any */
252 if ( pcfface->stream == &face->gzip_stream )
253 {
254 FT_Stream_Close( &face->gzip_stream );
255 pcfface->stream = face->gzip_source;
256 }
257 }
258
259
260 FT_CALLBACK_DEF( FT_Error )
261 PCF_Face_Init( FT_Stream stream,
262 FT_Face pcfface, /* PCF_Face */
263 FT_Int face_index,
264 FT_Int num_params,
265 FT_Parameter* params )
266 {
267 PCF_Face face = (PCF_Face)pcfface;
268 FT_Error error = PCF_Err_Ok;
269
270 FT_UNUSED( num_params );
271 FT_UNUSED( params );
272 FT_UNUSED( face_index );
273
274
275 error = pcf_load_font( stream, face );
276 if ( error )
277 {
278 PCF_Face_Done( pcfface );
279
280 #if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \
281 defined( FT_CONFIG_OPTION_USE_LZW )
282
283 #ifdef FT_CONFIG_OPTION_USE_ZLIB
284 {
285 FT_Error error2;
286
287
288 /* this didn't work, try gzip support! */
289 error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
290 if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
291 goto Fail;
292
293 error = error2;
294 }
295 #endif /* FT_CONFIG_OPTION_USE_ZLIB */
296
297 #ifdef FT_CONFIG_OPTION_USE_LZW
298 if ( error )
299 {
300 FT_Error error3;
301
302
303 /* this didn't work, try LZW support! */
304 error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );
305 if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
306 goto Fail;
307
308 error = error3;
309 }
310 #endif /* FT_CONFIG_OPTION_USE_LZW */
311
312 if ( error )
313 goto Fail;
314
315 face->gzip_source = stream;
316 pcfface->stream = &face->gzip_stream;
317
318 stream = pcfface->stream;
319
320 error = pcf_load_font( stream, face );
321 if ( error )
322 goto Fail;
323
324 #else /* !(FT_CONFIG_OPTION_USE_ZLIB || FT_CONFIG_OPTION_USE_LZW) */
325
326 goto Fail;
327
328 #endif
329 }
330
331 /* set up charmap */
332 {
333 FT_String *charset_registry = face->charset_registry;
334 FT_String *charset_encoding = face->charset_encoding;
335 FT_Bool unicode_charmap = 0;
336
337
338 if ( charset_registry && charset_encoding )
339 {
340 char* s = charset_registry;
341
342
343 /* Uh, oh, compare first letters manually to avoid dependency
344 on locales. */
345 if ( ( s[0] == 'i' || s[0] == 'I' ) &&
346 ( s[1] == 's' || s[1] == 'S' ) &&
347 ( s[2] == 'o' || s[2] == 'O' ) )
348 {
349 s += 3;
350 if ( !ft_strcmp( s, "10646" ) ||
351 ( !ft_strcmp( s, "8859" ) &&
352 !ft_strcmp( face->charset_encoding, "1" ) ) )
353 unicode_charmap = 1;
354 }
355 }
356
357 {
358 FT_CharMapRec charmap;
359
360
361 charmap.face = FT_FACE( face );
362 charmap.encoding = FT_ENCODING_NONE;
363 /* initial platform/encoding should indicate unset status? */
364 charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
365 charmap.encoding_id = TT_APPLE_ID_DEFAULT;
366
367 if ( unicode_charmap )
368 {
369 charmap.encoding = FT_ENCODING_UNICODE;
370 charmap.platform_id = TT_PLATFORM_MICROSOFT;
371 charmap.encoding_id = TT_MS_ID_UNICODE_CS;
372 }
373
374 error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );
375
376 #if 0
377 /* Select default charmap */
378 if ( pcfface->num_charmaps )
379 pcfface->charmap = pcfface->charmaps[0];
380 #endif
381 }
382 }
383
384 Exit:
385 return error;
386
387 Fail:
388 FT_TRACE2(( "[not a valid PCF file]\n" ));
389 PCF_Face_Done( pcfface );
390 error = PCF_Err_Unknown_File_Format; /* error */
391 goto Exit;
392 }
393
394
395 FT_CALLBACK_DEF( FT_Error )
396 PCF_Size_Select( FT_Size size,
397 FT_ULong strike_index )
398 {
399 PCF_Accel accel = &( (PCF_Face)size->face )->accel;
400
401
402 FT_Select_Metrics( size->face, strike_index );
403
404 size->metrics.ascender = accel->fontAscent << 6;
405 size->metrics.descender = -accel->fontDescent << 6;
406 size->metrics.max_advance = accel->maxbounds.characterWidth << 6;
407
408 return PCF_Err_Ok;
409 }
410
411
412 FT_CALLBACK_DEF( FT_Error )
413 PCF_Size_Request( FT_Size size,
414 FT_Size_Request req )
415 {
416 PCF_Face face = (PCF_Face)size->face;
417 FT_Bitmap_Size* bsize = size->face->available_sizes;
418 FT_Error error = PCF_Err_Invalid_Pixel_Size;
419 FT_Long height;
420
421
422 height = FT_REQUEST_HEIGHT( req );
423 height = ( height + 32 ) >> 6;
424
425 switch ( req->type )
426 {
427 case FT_SIZE_REQUEST_TYPE_NOMINAL:
428 if ( height == ( ( bsize->y_ppem + 32 ) >> 6 ) )
429 error = PCF_Err_Ok;
430 break;
431
432 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
433 if ( height == ( face->accel.fontAscent +
434 face->accel.fontDescent ) )
435 error = PCF_Err_Ok;
436 break;
437
438 default:
439 error = PCF_Err_Unimplemented_Feature;
440 break;
441 }
442
443 if ( error )
444 return error;
445 else
446 return PCF_Size_Select( size, 0 );
447 }
448
449
450 FT_CALLBACK_DEF( FT_Error )
451 PCF_Glyph_Load( FT_GlyphSlot slot,
452 FT_Size size,
453 FT_UInt glyph_index,
454 FT_Int32 load_flags )
455 {
456 PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );
457 FT_Stream stream;
458 FT_Error error = PCF_Err_Ok;
459 FT_Bitmap* bitmap = &slot->bitmap;
460 PCF_Metric metric;
461 FT_Offset bytes;
462
463 FT_UNUSED( load_flags );
464
465
466 FT_TRACE4(( "load_glyph %d ---", glyph_index ));
467
468 if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs )
469 {
470 error = PCF_Err_Invalid_Argument;
471 goto Exit;
472 }
473
474 stream = face->root.stream;
475
476 if ( glyph_index > 0 )
477 glyph_index--;
478
479 metric = face->metrics + glyph_index;
480
481 bitmap->rows = metric->ascent + metric->descent;
482 bitmap->width = metric->rightSideBearing - metric->leftSideBearing;
483 bitmap->num_grays = 1;
484 bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
485
486 FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
487 PCF_BIT_ORDER( face->bitmapsFormat ),
488 PCF_BYTE_ORDER( face->bitmapsFormat ),
489 PCF_GLYPH_PAD( face->bitmapsFormat ) ));
490
491 switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
492 {
493 case 1:
494 bitmap->pitch = ( bitmap->width + 7 ) >> 3;
495 break;
496
497 case 2:
498 bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
499 break;
500
501 case 4:
502 bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
503 break;
504
505 case 8:
506 bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
507 break;
508
509 default:
510 return PCF_Err_Invalid_File_Format;
511 }
512
513 /* XXX: to do: are there cases that need repadding the bitmap? */
514 bytes = bitmap->pitch * bitmap->rows;
515
516 error = ft_glyphslot_alloc_bitmap( slot, bytes );
517 if ( error )
518 goto Exit;
519
520 if ( FT_STREAM_SEEK( metric->bits ) ||
521 FT_STREAM_READ( bitmap->buffer, bytes ) )
522 goto Exit;
523
524 if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
525 BitOrderInvert( bitmap->buffer, bytes );
526
527 if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
528 PCF_BIT_ORDER( face->bitmapsFormat ) ) )
529 {
530 switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
531 {
532 case 1:
533 break;
534
535 case 2:
536 TwoByteSwap( bitmap->buffer, bytes );
537 break;
538
539 case 4:
540 FourByteSwap( bitmap->buffer, bytes );
541 break;
542 }
543 }
544
545 slot->format = FT_GLYPH_FORMAT_BITMAP;
546 slot->bitmap_left = metric->leftSideBearing;
547 slot->bitmap_top = metric->ascent;
548
549 slot->metrics.horiAdvance = metric->characterWidth << 6;
550 slot->metrics.horiBearingX = metric->leftSideBearing << 6;
551 slot->metrics.horiBearingY = metric->ascent << 6;
552 slot->metrics.width = ( metric->rightSideBearing -
553 metric->leftSideBearing ) << 6;
554 slot->metrics.height = bitmap->rows << 6;
555
556 ft_synthesize_vertical_metrics( &slot->metrics,
557 ( face->accel.fontAscent +
558 face->accel.fontDescent ) << 6 );
559
560 FT_TRACE4(( " --- ok\n" ));
561
562 Exit:
563 return error;
564 }
565
566
567 /*
568 *
569 * BDF SERVICE
570 *
571 */
572
573 static FT_Error
574 pcf_get_bdf_property( PCF_Face face,
575 const char* prop_name,
576 BDF_PropertyRec *aproperty )
577 {
578 PCF_Property prop;
579
580
581 prop = pcf_find_property( face, prop_name );
582 if ( prop != NULL )
583 {
584 if ( prop->isString )
585 {
586 aproperty->type = BDF_PROPERTY_TYPE_ATOM;
587 aproperty->u.atom = prop->value.atom;
588 }
589 else
590 {
591 if ( prop->value.l > 0x7FFFFFFFL || prop->value.l < ( -1 - 0x7FFFFFFFL ) )
592 {
593 FT_TRACE1(( "pcf_get_bdf_property: " ));
594 FT_TRACE1(( "too large integer 0x%x is truncated\n" ));
595 }
596 /* Apparently, the PCF driver loads all properties as signed integers!
597 * This really doesn't seem to be a problem, because this is
598 * sufficient for any meaningful values.
599 */
600 aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
601 aproperty->u.integer = (FT_Int32)prop->value.l;
602 }
603 return 0;
604 }
605
606 return PCF_Err_Invalid_Argument;
607 }
608
609
610 static FT_Error
611 pcf_get_charset_id( PCF_Face face,
612 const char* *acharset_encoding,
613 const char* *acharset_registry )
614 {
615 *acharset_encoding = face->charset_encoding;
616 *acharset_registry = face->charset_registry;
617
618 return 0;
619 }
620
621
622 static const FT_Service_BDFRec pcf_service_bdf =
623 {
624 (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id,
625 (FT_BDF_GetPropertyFunc) pcf_get_bdf_property
626 };
627
628
629 /*
630 *
631 * SERVICE LIST
632 *
633 */
634
635 static const FT_ServiceDescRec pcf_services[] =
636 {
637 { FT_SERVICE_ID_BDF, &pcf_service_bdf },
638 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF },
639 { NULL, NULL }
640 };
641
642
643 FT_CALLBACK_DEF( FT_Module_Interface )
644 pcf_driver_requester( FT_Module module,
645 const char* name )
646 {
647 FT_UNUSED( module );
648
649 return ft_service_list_lookup( pcf_services, name );
650 }
651
652
653 FT_CALLBACK_TABLE_DEF
654 const FT_Driver_ClassRec pcf_driver_class =
655 {
656 {
657 FT_MODULE_FONT_DRIVER |
658 FT_MODULE_DRIVER_NO_OUTLINES,
659 sizeof ( FT_DriverRec ),
660
661 "pcf",
662 0x10000L,
663 0x20000L,
664
665 0,
666
667 0,
668 0,
669 pcf_driver_requester
670 },
671
672 sizeof ( PCF_FaceRec ),
673 sizeof ( FT_SizeRec ),
674 sizeof ( FT_GlyphSlotRec ),
675
676 PCF_Face_Init,
677 PCF_Face_Done,
678 0, /* FT_Size_InitFunc */
679 0, /* FT_Size_DoneFunc */
680 0, /* FT_Slot_InitFunc */
681 0, /* FT_Slot_DoneFunc */
682
683 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
684 ft_stub_set_char_sizes,
685 ft_stub_set_pixel_sizes,
686 #endif
687 PCF_Glyph_Load,
688
689 0, /* FT_Face_GetKerningFunc */
690 0, /* FT_Face_AttachFunc */
691 0, /* FT_Face_GetAdvancesFunc */
692
693 PCF_Size_Request,
694 PCF_Size_Select
695 };
696
697
698 /* END */