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