blob: 81e0e8a9bcd3cab77e75de55037d445dae5ff315 [file] [log] [blame]
Werner Lemberg347a7142002-05-15 06:16:57 +00001/***************************************************************************/
2/* */
3/* t42drivr.c */
4/* */
5/* FreeType font driver for Type 42 fonts (body only). */
6/* */
7/* Copyright 2002 by Roberto Alameda. */
8/* */
9/* This file is part of the FreeType project, and may only be used, */
10/* modified, and distributed under the terms of the FreeType project */
11/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
12/* this file you indicate that you have read the license and */
13/* understand and accept it fully. */
14/* */
15/***************************************************************************/
16
17
18#include <ft2build.h>
19#define FT_ERR_PREFIX T42_Err_
20#define FT_ERR_BASE FT_Mod_Err_Type42
21
22#include FT_CONFIG_STANDARD_LIBRARY_H
23
24#include FT_INTERNAL_DEBUG_H
25#include FT_CONFIG_CONFIG_H
26
27#include FT_ERRORS_H
28#include FT_FREETYPE_H
29#include FT_TYPE1_TABLES_H
30#include FT_LIST_H
31
32#include FT_INTERNAL_DRIVER_H
33#include FT_INTERNAL_OBJECTS_H
34#include FT_INTERNAL_TYPE1_TYPES_H
35#include FT_INTERNAL_POSTSCRIPT_AUX_H
36#include FT_INTERNAL_STREAM_H
37
38
39 /********************* Data Definitions ******************/
40
41 typedef enum T42_EncodingType_
42 {
43 T42_ENCODING_TYPE_NONE = 0,
44 T42_ENCODING_TYPE_ARRAY,
45 T42_ENCODING_TYPE_STANDARD,
46 T42_ENCODING_TYPE_EXPERT,
47 T42_ENCODING_TYPE_ISOLATIN1
48
49 } T42_EncodingType;
50
51
52 typedef struct T42_Font_
53 {
54 /* font info dictionary */
55 PS_FontInfoRec font_info;
56
57 /* top-level dictionary */
58 FT_String* font_name;
59
60 T42_EncodingType encoding_type;
61 T1_EncodingRec encoding;
62
63 FT_Byte* charstrings_block;
64 FT_Byte* glyph_names_block;
65
66 FT_Int num_glyphs;
67 FT_String** glyph_names; /* array of glyph names */
68 FT_Byte** charstrings; /* array of glyph charstrings */
69 FT_Int* charstrings_len;
70
71 FT_Byte paint_type;
72 FT_Byte font_type;
73 FT_Matrix font_matrix; /* From FontMatrix field: a, b, c, d */
74 FT_Vector font_offset; /* From FontMatrix field: tx, ty */
75 FT_BBox font_bbox;
76
77 FT_Int stroke_width;
78
79 } T42_FontRec, *T42_Font;
80
81
82 typedef struct T42_FaceRec_
83 {
84 FT_FaceRec root;
85 T42_FontRec type42;
86 void* psnames;
87 void* psaux;
88 void* afm_data;
89 FT_Byte* ttf_data;
90 FT_ULong ttf_size;
91 FT_Face ttf_face;
92 FT_CharMapRec charmaprecs[2];
93 FT_CharMap charmaps[2];
94 PS_Unicodes unicode_map;
95
96 } T42_FaceRec, *T42_Face;
97
98
99 typedef struct T42_DriverRec_
100 {
101 FT_DriverRec root;
102 FT_Driver_Class ttclazz;
103 void* extension_component;
104
105 } T42_DriverRec, *T42_Driver;
106
107
108 typedef struct T42_SizeRec_
109 {
110 FT_SizeRec root;
111 FT_Size ttsize;
112
113 } T42_SizeRec, *T42_Size;
114
115
116 typedef struct T42_GlyphSlotRec_
117 {
118 FT_GlyphSlotRec root;
119 FT_GlyphSlot ttslot;
120
121 } T42_GlyphSlotRec, *T42_GlyphSlot;
122
123
124 /*********** Parser definitions *************/
125
126 typedef struct T42_ParserRec_
127 {
128 PS_ParserRec root;
129 FT_Stream stream;
130
131 FT_Byte* base_dict;
132 FT_Int base_len;
133
134 FT_Byte in_memory;
135
136 } T42_ParserRec, *T42_Parser;
137
138
139 typedef struct T42_Loader_
140 {
141 T42_ParserRec parser; /* parser used to read the stream */
142
143 FT_Int num_chars; /* number of characters in encoding */
144 PS_TableRec encoding_table; /* PS_Table used to store the */
145 /* encoding character names */
146
147 FT_Int num_glyphs;
148 PS_TableRec glyph_names;
149 PS_TableRec charstrings;
150
151 } T42_LoaderRec, *T42_Loader;
152
153
154 /*********************** Prototypes *********************/
155
156 static void
157 parse_font_name( T42_Face face,
158 T42_Loader loader );
159 static void
160 parse_font_bbox( T42_Face face,
161 T42_Loader loader );
162 static void
163 parse_font_matrix( T42_Face face,
164 T42_Loader loader );
165 static void
166 parse_encoding( T42_Face face,
167 T42_Loader loader );
168 static void
169 parse_charstrings( T42_Face face,
170 T42_Loader loader );
171 static void
172 parse_sfnts( T42_Face face,
173 T42_Loader loader );
174
175
176 static const
177 T1_FieldRec t42_keywords[] = {
178
179#undef FT_STRUCTURE
180#define FT_STRUCTURE T1_FontInfo
181#undef T1CODE
182#define T1CODE T1_FIELD_LOCATION_FONT_INFO
183
184 T1_FIELD_STRING ( "version", version )
185 T1_FIELD_STRING ( "Notice", notice )
186 T1_FIELD_STRING ( "FullName", full_name )
187 T1_FIELD_STRING ( "FamilyName", family_name )
188 T1_FIELD_STRING ( "Weight", weight )
189 T1_FIELD_NUM ( "ItalicAngle", italic_angle )
190 T1_FIELD_TYPE_BOOL( "isFixedPitch", is_fixed_pitch )
191 T1_FIELD_NUM ( "UnderlinePosition", underline_position )
192 T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )
193
194#undef FT_STRUCTURE
195#define FT_STRUCTURE T42_FontRec
196#undef T1CODE
197#define T1CODE T1_FIELD_LOCATION_FONT_DICT
198
199 T1_FIELD_NUM( "PaintType", paint_type )
200 T1_FIELD_NUM( "FontType", font_type )
201 T1_FIELD_NUM( "StrokeWidth", stroke_width )
202
203 T1_FIELD_CALLBACK( "FontName", parse_font_name )
204 T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
205 T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
206 T1_FIELD_CALLBACK( "Encoding", parse_encoding )
207 T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
208 T1_FIELD_CALLBACK( "sfnts", parse_sfnts )
209
210 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
211 };
212
213
214#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
215#define T1_Done_Table( p ) \
216 do \
217 { \
218 if ( (p)->funcs.done ) \
219 (p)->funcs.done( p ); \
220 } while ( 0 )
221#define T1_Release_Table( p ) \
222 do \
223 { \
224 if ( (p)->funcs.release ) \
225 (p)->funcs.release( p ); \
226 } while ( 0 )
227
228#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
229#define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
230
231#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
232#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
233
234#define T1_ToCoordArray( p, m, c ) \
235 (p)->root.funcs.to_coord_array( &(p)->root, m, c )
236#define T1_ToFixedArray( p, m, f, t ) \
237 (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
238#define T1_ToToken( p, t ) \
239 (p)->root.funcs.to_token( &(p)->root, t )
240#define T1_ToTokenArray( p, t, m, c ) \
241 (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
242
243#define T1_Load_Field( p, f, o, m, pf ) \
244 (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
245#define T1_Load_Field_Table( p, f, o, m, pf ) \
246 (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
247
248
249 /********************* Parsing Functions ******************/
250
251 static FT_Error
252 T42_New_Parser( T42_Parser parser,
253 FT_Stream stream,
254 FT_Memory memory,
255 PSAux_Service psaux )
256 {
257 FT_Error error = T42_Err_Ok;
258 FT_Long size;
259
260
261 psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
262
263 parser->stream = stream;
264 parser->base_len = 0;
265 parser->base_dict = 0;
266 parser->in_memory = 0;
267
268 /*******************************************************************/
269 /* */
270 /* Here a short summary of what is going on: */
271 /* */
272 /* When creating a new Type 42 parser, we try to locate and load */
273 /* the base dictionary, loading the whole font into memory. */
274 /* */
275 /* When `loading' the base dictionary, we only setup pointers in */
276 /* the case of a memory-based stream. Otherwise, we allocate */
277 /* and load the base dictionary in it. */
278 /* */
279 /* parser->in_memory is set if we have a memory stream. */
280 /* */
281
282 if ( FT_STREAM_SEEK( 0L ) )
283 goto Exit;
284
285 size = stream->size;
286
287 /* now, try to load `size' bytes of the `base' dictionary we */
288 /* found previously */
289
290 /* if it is a memory-based resource, set up pointers */
291 if ( !stream->read )
292 {
293 parser->base_dict = (FT_Byte*)stream->base + stream->pos;
294 parser->base_len = size;
295 parser->in_memory = 1;
296
297 /* check that the `size' field is valid */
298 if ( FT_STREAM_SKIP( size ) )
299 goto Exit;
300 }
301 else
302 {
303 /* read segment in memory */
304 if (FT_ALLOC( parser->base_dict, size ) ||
305 FT_STREAM_READ( parser->base_dict, size ) )
306 goto Exit;
307 parser->base_len = size;
308 }
309
310 /* Now check font format; we must see `%!PS-TrueTypeFont' */
311 if (size <= 17 ||
312 ( ft_strncmp( (const char*)parser->base_dict,
313 "%!PS-TrueTypeFont", 17) ) )
314 error = T42_Err_Unknown_File_Format;
315 else
316 {
317 parser->root.base = parser->base_dict;
318 parser->root.cursor = parser->base_dict;
319 parser->root.limit = parser->root.cursor + parser->base_len;
320 }
321
322 Exit:
323 if ( error && !parser->in_memory )
324 FT_FREE( parser->base_dict );
325
326 return error;
327 }
328
329
330 static void
331 T42_Finalize_Parser( T42_Parser parser )
332 {
333 FT_Memory memory = parser->root.memory;
334
335
336 /* free the base dictionary only when we have a disk stream */
337 if ( !parser->in_memory )
338 FT_FREE( parser->base_dict );
339
340 parser->root.funcs.done( &parser->root );
341 }
342
343
344 static int
345 is_alpha( FT_Byte c )
346 {
347 /* Note: we must accept "+" as a valid character, as it is used in */
348 /* embedded type1 fonts in PDF documents. */
349 /* */
350 return ( ft_isalnum( c ) ||
351 c == '.' ||
352 c == '_' ||
353 c == '-' ||
354 c == '+' );
355 }
356
357
358 static int
359 is_space( FT_Byte c )
360 {
361 return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
362 }
363
364
365 static void
366 parse_font_name( T42_Face face,
367 T42_Loader loader )
368 {
369 T42_Parser parser = &loader->parser;
370 FT_Error error;
371 FT_Memory memory = parser->root.memory;
372 FT_Int len;
373 FT_Byte* cur;
374 FT_Byte* cur2;
375 FT_Byte* limit;
376
377
378 T1_Skip_Spaces( parser );
379
380 cur = parser->root.cursor;
381 limit = parser->root.limit;
382
383 if ( cur >= limit - 1 ||
384 ( *cur != '/' && *cur != '(') )
385 return;
386
387 cur++;
388 cur2 = cur;
389 while ( cur2 < limit && is_alpha( *cur2 ) )
390 cur2++;
391
392 len = (FT_Int)( cur2 - cur );
393 if ( len > 0 )
394 {
395 if ( FT_ALLOC( face->type42.font_name, len + 1 ) )
396 {
397 parser->root.error = error;
398 return;
399 }
400
401 FT_MEM_COPY( face->type42.font_name, cur, len );
402 face->type42.font_name[len] = '\0';
403 }
404 parser->root.cursor = cur2;
405 }
406
407
408 static void
409 parse_font_bbox( T42_Face face,
410 T42_Loader loader )
411 {
412 T42_Parser parser = &loader->parser;
413 FT_BBox* bbox = &face->type42.font_bbox;
414
415 bbox->xMin = T1_ToInt( parser );
416 bbox->yMin = T1_ToInt( parser );
417 bbox->xMax = T1_ToInt( parser );
418 bbox->yMax = T1_ToInt( parser );
419 }
420
421
422 static void
423 parse_font_matrix( T42_Face face,
424 T42_Loader loader )
425 {
426 T42_Parser parser = &loader->parser;
427 FT_Matrix* matrix = &face->type42.font_matrix;
428 FT_Vector* offset = &face->type42.font_offset;
429 FT_Face root = (FT_Face)&face->root;
430 FT_Fixed temp[6];
431 FT_Fixed temp_scale;
432
433
434 /* XXX: Are these three lines necessary */
435 if ( matrix->xx || matrix->yx )
436 /* with synthetic fonts, it's possible we get here twice */
437 return;
438
439 (void)T1_ToFixedArray( parser, 6, temp, 3 );
440
441 temp_scale = ABS( temp[3] );
442
443 /* Set Units per EM based on FontMatrix values. We set the value to */
444 /* 1000 / temp_scale, because temp_scale was already multiplied by */
445 /* 1000 (in t1_tofixed, from psobjs.c). */
446
447 root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
448 temp_scale ) >> 16 );
449
450 /* we need to scale the values by 1.0/temp_scale */
451 if ( temp_scale != 0x10000L ) {
452 temp[0] = FT_DivFix( temp[0], temp_scale );
453 temp[1] = FT_DivFix( temp[1], temp_scale );
454 temp[2] = FT_DivFix( temp[2], temp_scale );
455 temp[4] = FT_DivFix( temp[4], temp_scale );
456 temp[5] = FT_DivFix( temp[5], temp_scale );
457 temp[3] = 0x10000L;
458 }
459
460 matrix->xx = temp[0];
461 matrix->yx = temp[1];
462 matrix->xy = temp[2];
463 matrix->yy = temp[3];
464
465 /* note that the offsets must be expressed in integer font units */
466 offset->x = temp[4] >> 16;
467 offset->y = temp[5] >> 16;
468 }
469
470
471 static void
472 parse_encoding( T42_Face face,
473 T42_Loader loader )
474 {
475 T42_Parser parser = &loader->parser;
476 FT_Byte* cur = parser->root.cursor;
477 FT_Byte* limit = parser->root.limit;
478
479 PSAux_Service psaux = (PSAux_Service)face->psaux;
480
481
482 /* skip whitespace */
483 while ( is_space( *cur ) )
484 {
485 cur++;
486 if ( cur >= limit )
487 {
488 FT_ERROR(( "parse_encoding: out of bounds!\n" ));
489 parser->root.error = T42_Err_Invalid_File_Format;
490 return;
491 }
492 }
493
494 /* if we have a number, then the encoding is an array, */
495 /* and we must load it now */
496 if ( (FT_Byte)( *cur - '0' ) < 10 )
497 {
498 T1_Encoding encode = &face->type42.encoding;
499 FT_Int count, n;
500 PS_Table char_table = &loader->encoding_table;
501 FT_Memory memory = parser->root.memory;
502 FT_Error error;
503
504
505 /* read the number of entries in the encoding, should be 256 */
506 count = T1_ToInt( parser );
507 if ( parser->root.error )
508 return;
509
510 /* we use a T1_Table to store our charnames */
511 loader->num_chars = encode->num_chars = count;
512 if ( FT_NEW_ARRAY( encode->char_index, count ) ||
513 FT_NEW_ARRAY( encode->char_name, count ) ||
514 FT_SET_ERROR( psaux->ps_table_funcs->init(
515 char_table, count, memory ) ) )
516 {
517 parser->root.error = error;
518 return;
519 }
520
521 /* We need to `zero' out encoding_table.elements */
522 for ( n = 0; n < count; n++ )
523 {
524 char* notdef = (char *)".notdef";
525
526
527 T1_Add_Table( char_table, n, notdef, 8 );
528 }
529
530 /* Now, we will need to read a record of the form */
531 /* ... charcode /charname ... for each entry in our table */
532 /* */
533 /* We simply look for a number followed by an immediate */
534 /* name. Note that this ignores correctly the sequence */
535 /* that is often seen in type1 fonts: */
536 /* */
537 /* 0 1 255 { 1 index exch /.notdef put } for dup */
538 /* */
539 /* used to clean the encoding array before anything else. */
540 /* */
541 /* We stop when we encounter a `def'. */
542
543 cur = parser->root.cursor;
544 limit = parser->root.limit;
545 n = 0;
546
547 for ( ; cur < limit; )
548 {
549 FT_Byte c;
550
551
552 c = *cur;
553
554 /* we stop when we encounter a `def' */
555 if ( c == 'd' && cur + 3 < limit )
556 {
557 if ( cur[1] == 'e' &&
558 cur[2] == 'f' &&
559 is_space( cur[-1] ) &&
560 is_space( cur[3] ) )
561 {
562 FT_TRACE6(( "encoding end\n" ));
563 break;
564 }
565 }
566
567 /* otherwise, we must find a number before anything else */
568 if ( (FT_Byte)( c - '0' ) < 10 )
569 {
570 FT_Int charcode;
571
572
573 parser->root.cursor = cur;
574 charcode = T1_ToInt( parser );
575 cur = parser->root.cursor;
576
577 /* skip whitespace */
578 while ( cur < limit && is_space( *cur ) )
579 cur++;
580
581 if ( cur < limit && *cur == '/' )
582 {
583 /* bingo, we have an immediate name -- it must be a */
584 /* character name */
585 FT_Byte* cur2 = cur + 1;
586 FT_Int len;
587
588
589 while ( cur2 < limit && is_alpha( *cur2 ) )
590 cur2++;
591
592 len = (FT_Int)( cur2 - cur - 1 );
593
594 parser->root.error = T1_Add_Table( char_table, charcode,
595 cur + 1, len + 1 );
596 char_table->elements[charcode][len] = '\0';
597 if ( parser->root.error )
598 return;
599
600 cur = cur2;
601 }
602 }
603 else
604 cur++;
605 }
606
607 face->type42.encoding_type = T42_ENCODING_TYPE_ARRAY;
608 parser->root.cursor = cur;
609 }
610 /* Otherwise, we should have either `StandardEncoding', */
611 /* `ExpertEncoding', or `ISOLatin1Encoding' */
612 else
613 {
614 if ( cur + 17 < limit &&
615 ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
616 face->type42.encoding_type = T42_ENCODING_TYPE_STANDARD;
617
618 else if ( cur + 15 < limit &&
619 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
620 face->type42.encoding_type = T42_ENCODING_TYPE_EXPERT;
621
622 else if ( cur + 18 < limit &&
623 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
624 face->type42.encoding_type = T42_ENCODING_TYPE_ISOLATIN1;
625
626 else {
627 FT_ERROR(( "parse_encoding: invalid token!\n" ));
628 parser->root.error = T42_Err_Invalid_File_Format;
629 }
630 }
631 }
632
633
634 static FT_Byte
635 hexval( FT_Byte v )
636 {
637 if ( v >= 'A' && v <= 'F' )
638 return v - 'A' + 10;
639 if ( v >= 'a' && v <= 'f' )
640 return v - 'a' + 10;
641 if ( v >= '0' && v <= '9' )
642 return v - '0';
643
644 return 0;
645 }
646
647
648 static void
649 parse_sfnts( T42_Face face,
650 T42_Loader loader )
651 {
652 T42_Parser parser = &loader->parser;
653 FT_Memory memory = parser->root.memory;
654 FT_Byte* cur = parser->root.cursor;
655 FT_Byte* limit = parser->root.limit;
656 FT_Error error;
657 FT_Int num_tables, status;
658 FT_ULong count, ttf_size, string_size;
659 FT_Bool in_string = 0;
660 FT_Byte v;
661
662
663 /* The format is `/sfnts [ <...> <...> ... ] def' */
664
665 while ( is_space( *cur ) )
666 cur++;
667
668 if (*cur++ == '[')
669 {
670 status = 0;
671 count = 0;
672 }
673 else
674 {
675 FT_ERROR(( "parse_sfnts: can't find begin of sfnts vector!\n" ));
676 error = T42_Err_Invalid_File_Format;
677 goto Fail;
678 }
679
680 while ( cur < limit - 2 )
681 {
682 while ( is_space( *cur ) )
683 cur++;
684
685 switch ( *cur )
686 {
687 case ']':
688 parser->root.cursor = cur++;
689 return;
690
691 case '<':
692 in_string = 1;
693 string_size = 0;
694 cur++;
695 continue;
696
697 case '>':
698 if ( !in_string )
699 {
700 FT_ERROR(( "parse_sfnts: found unpaired `>'!\n" ));
701 error = T42_Err_Invalid_File_Format;
702 goto Fail;
703 }
704
705 /* A string can have, as a last byte, */
706 /* a zero byte for padding. If so, ignore it */
707 if ( ( v == 0 ) && ( string_size % 2 == 1 ) )
708 count--;
709 in_string = 0;
710 cur++;
711 continue;
712
713 case '%':
714 if ( !in_string )
715 {
716 /* Comment found; skip till end of line */
717 while ( *cur != '\n' )
718 cur++;
719 continue;
720 }
721 else
722 {
723 FT_ERROR(( "parse_sfnts: found `%' in string!\n" ));
724 error = T42_Err_Invalid_File_Format;
725 goto Fail;
726 }
727
728 default:
729 if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
730 {
731 FT_ERROR(( "parse_sfnts: found non-hex characters in string" ));
732 error = T42_Err_Invalid_File_Format;
733 goto Fail;
734 }
735
736 v = 16 * hexval( *cur++ ) + hexval( *cur++ );
737 string_size++;
738 }
739
740 switch ( status )
741 {
742 case 0: /* The '[' was read, so load offset table, 12 bytes */
743 if ( count < 12 )
744 {
745 face->ttf_data[count++] = v;
746 continue;
747 }
748 else
749 {
750 num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
751 status = 1;
752 ttf_size = 12 + 16 * num_tables;
753
754 if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
755 goto Fail;
756 }
757 /* No break, fall-through */
758
759 case 1: /* The offset table is read; read now the table directory */
760 if ( count < ttf_size )
761 {
762 face->ttf_data[count++] = v;
763 continue;
764 }
765 else
766 {
767 int i;
768 FT_ULong len;
769
770
771 for ( i = 0; i < num_tables; i++ )
772 {
773 len = face->ttf_data[12 + 16*i + 12 + 0] << 24;
774 len += face->ttf_data[12 + 16*i + 12 + 1] << 16;
775 len += face->ttf_data[12 + 16*i + 12 + 2] << 8;
776 len += face->ttf_data[12 + 16*i + 12 + 3];
777
778 /* Pad to a 4-byte boundary length */
779 ttf_size += ( len + 3 ) & ~3;
780 }
781
782 status = 2;
783 face->ttf_size = ttf_size;
784
785 if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
786 ttf_size + 1 ) )
787 goto Fail;
788 }
789 /* No break, fall-through */
790
791 case 2: /* We are reading normal tables; just swallow them */
792 face->ttf_data[count++] = v;
793
794 }
795 }
796
797 /* If control reaches this point, the format was not valid */
798 error = T42_Err_Invalid_File_Format;
799
800 Fail:
801 parser->root.error = error;
802 }
803
804
805 static void
806 parse_charstrings( T42_Face face,
807 T42_Loader loader )
808 {
809 T42_Parser parser = &loader->parser;
810 PS_Table code_table = &loader->charstrings;
811 PS_Table name_table = &loader->glyph_names;
812 FT_Memory memory = parser->root.memory;
813 FT_Error error;
814
815 PSAux_Service psaux = (PSAux_Service)face->psaux;
816
817 FT_Byte* cur;
818 FT_Byte* limit = parser->root.limit;
819 FT_Int n;
820
821
822 loader->num_glyphs = T1_ToInt( parser );
823 if ( parser->root.error )
824 return;
825
826 /* initialize tables */
827
828 error = psaux->ps_table_funcs->init( code_table,
829 loader->num_glyphs,
830 memory );
831 if ( error )
832 goto Fail;
833
834 error = psaux->ps_table_funcs->init( name_table,
835 loader->num_glyphs,
836 memory );
837 if ( error )
838 goto Fail;
839
840 n = 0;
841
842 for (;;)
843 {
844 /* the format is simple: */
845 /* `/glyphname' + index + def */
846 /* */
847 /* note that we stop when we find an `end' */
848 /* */
849 T1_Skip_Spaces( parser );
850
851 cur = parser->root.cursor;
852 if ( cur >= limit )
853 break;
854
855 /* we stop when we find an `end' keyword */
856 if ( *cur == 'e' &&
857 cur + 3 < limit &&
858 cur[1] == 'n' &&
859 cur[2] == 'd' )
860 break;
861
862 if ( *cur != '/' )
863 T1_Skip_Alpha( parser );
864 else
865 {
866 FT_Byte* cur2 = cur + 1;
867 FT_Int len;
868
869
870 while ( cur2 < limit && is_alpha( *cur2 ) )
871 cur2++;
872 len = (FT_Int)( cur2 - cur - 1 );
873
874 error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
875 if ( error )
876 goto Fail;
877
878 /* add a trailing zero to the name table */
879 name_table->elements[n][len] = '\0';
880
881 parser->root.cursor = cur2;
882 T1_Skip_Spaces( parser );
883
884 cur2 = cur = parser->root.cursor;
885 if ( cur >= limit )
886 break;
887
888 while ( cur2 < limit && is_alpha( *cur2 ) )
889 cur2++;
890 len = (FT_Int)( cur2 - cur );
891
892 error = T1_Add_Table( code_table, n, cur, len + 1 );
893 if ( error )
894 goto Fail;
895
896 code_table->elements[n][len] = '\0';
897
898 n++;
899 if ( n >= loader->num_glyphs )
900 break;
901 }
902 }
903
904 /* Index 0 must be a .notdef element */
905 if ( ft_strcmp( (char *)name_table->elements[0], ".notdef" ) )
906 {
907 FT_ERROR(( "parse_charstrings: Index 0 is not `.notdef'!\n" ));
908 error = T42_Err_Invalid_File_Format;
909 goto Fail;
910 }
911
912 loader->num_glyphs = n;
913 return;
914
915 Fail:
916 parser->root.error = error;
917 }
918
919
920 static FT_Error
921 t42_load_keyword( T42_Face face,
922 T42_Loader loader,
923 T1_Field field )
924 {
925 FT_Error error;
926 void* dummy_object;
927 void** objects;
928 FT_UInt max_objects = 0;
929
930
931 /* if the keyword has a dedicated callback, call it */
932 if ( field->type == T1_FIELD_TYPE_CALLBACK ) {
933 field->reader( (FT_Face)face, loader );
934 error = loader->parser.root.error;
935 goto Exit;
936 }
937
938 /* now, the keyword is either a simple field, or a table of fields; */
939 /* we are now going to take care of it */
940 switch ( field->location )
941 {
942 case T1_FIELD_LOCATION_FONT_INFO:
943 dummy_object = &face->type42.font_info;
944 objects = &dummy_object;
945 break;
946
947 default:
948 dummy_object = &face->type42;
949 objects = &dummy_object;
950 }
951
952 if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
953 field->type == T1_FIELD_TYPE_FIXED_ARRAY )
954 error = T1_Load_Field_Table( &loader->parser, field,
955 objects, max_objects, 0 );
956 else
957 error = T1_Load_Field( &loader->parser, field,
958 objects, max_objects, 0 );
959
960 Exit:
961 return error;
962 }
963
964
965 static FT_Error
966 parse_dict( T42_Face face,
967 T42_Loader loader,
968 FT_Byte* base,
969 FT_Long size )
970 {
971 T42_Parser parser = &loader->parser;
972 FT_Byte* cur = base;
973 FT_Byte* limit = cur + size;
974 FT_UInt n_keywords = sizeof ( t42_keywords ) /
975 sizeof ( t42_keywords[0] );
976
977
978 parser->root.cursor = base;
979 parser->root.limit = base + size;
980 parser->root.error = 0;
981
982 for ( ; cur < limit; cur++ )
983 {
984 /* look for `FontDirectory', which causes problems on some fonts */
985 if ( *cur == 'F' && cur + 25 < limit &&
986 ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
987 {
988 FT_Byte* cur2;
989
990
991 /* skip the `FontDirectory' keyword */
992 cur += 13;
993 cur2 = cur;
994
995 /* lookup the `known' keyword */
996 while ( cur < limit && *cur != 'k' &&
997 ft_strncmp( (char*)cur, "known", 5 ) )
998 cur++;
999
1000 if ( cur < limit )
1001 {
1002 T1_TokenRec token;
1003
1004
1005 /* skip the `known' keyword and the token following it */
1006 cur += 5;
1007 loader->parser.root.cursor = cur;
1008 T1_ToToken( &loader->parser, &token );
1009
1010 /* if the last token was an array, skip it! */
1011 if ( token.type == T1_TOKEN_TYPE_ARRAY )
1012 cur2 = parser->root.cursor;
1013 }
1014 cur = cur2;
1015 }
1016 /* look for immediates */
1017 else if ( *cur == '/' && cur + 2 < limit )
1018 {
1019 FT_Byte* cur2;
1020 FT_UInt i, len;
1021
1022
1023 cur++;
1024 cur2 = cur;
1025 while ( cur2 < limit && is_alpha( *cur2 ) )
1026 cur2++;
1027
1028 len = (FT_UInt)( cur2 - cur );
1029 if ( len > 0 && len < 22 ) /* XXX What shall it this 22? */
1030 {
1031 /* now, compare the immediate name to the keyword table */
1032
1033 /* Loop through all known keywords */
1034 for ( i = 0; i < n_keywords; i++ )
1035 {
1036 T1_Field keyword = (T1_Field)&t42_keywords[i];
1037 FT_Byte *name = (FT_Byte*)keyword->ident;
1038
1039
1040 if ( !name )
1041 continue;
1042
1043 if ( ( len == ft_strlen( (const char *)name ) ) &&
1044 ( ft_memcmp( cur, name, len ) == 0 ) )
1045 {
1046 /* we found it -- run the parsing callback! */
1047 parser->root.cursor = cur2;
1048 T1_Skip_Spaces( parser );
1049 parser->root.error = t42_load_keyword(face,
1050 loader,
1051 keyword );
1052 if ( parser->root.error )
1053 return parser->root.error;
1054 cur = parser->root.cursor;
1055 break;
1056 }
1057 }
1058 }
1059 }
1060 }
1061 return parser->root.error;
1062 }
1063
1064
1065 static void
1066 t42_init_loader( T42_Loader loader,
1067 T42_Face face )
1068 {
1069 FT_UNUSED( face );
1070
1071 FT_MEM_SET( loader, 0, sizeof ( *loader ) );
1072 loader->num_glyphs = 0;
1073 loader->num_chars = 0;
1074
1075 /* initialize the tables -- simply set their `init' field to 0 */
1076 loader->encoding_table.init = 0;
1077 loader->charstrings.init = 0;
1078 loader->glyph_names.init = 0;
1079 }
1080
1081
1082 static void
1083 t42_done_loader( T42_Loader loader )
1084 {
1085 T42_Parser parser = &loader->parser;
1086
1087
1088 /* finalize tables */
1089 T1_Release_Table( &loader->encoding_table );
1090 T1_Release_Table( &loader->charstrings );
1091 T1_Release_Table( &loader->glyph_names );
1092
1093 /* finalize parser */
1094 T42_Finalize_Parser( parser );
1095 }
1096
1097
1098 static FT_Error
1099 T42_Open_Face( T42_Face face )
1100 {
1101 T42_LoaderRec loader;
1102 T42_Parser parser;
1103 T42_Font type42 = &face->type42;
1104 FT_Memory memory = face->root.memory;
1105 FT_Error error;
1106
1107 PSAux_Service psaux = (PSAux_Service)face->psaux;
1108
1109
1110 t42_init_loader( &loader, face );
1111
1112 parser = &loader.parser;
1113
1114 if ( FT_ALLOC( face->ttf_data, 12 ) )
1115 goto Exit;
1116
1117 error = T42_New_Parser( parser,
1118 face->root.stream,
1119 memory,
1120 psaux);
1121 if ( error )
1122 goto Exit;
1123
1124 error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
1125
1126 if ( type42->font_type != 42 )
1127 {
1128 error = T42_Err_Unknown_File_Format;
1129 goto Exit;
1130 }
1131
1132 /* now, propagate the charstrings and glyphnames tables */
1133 /* to the Type42 data */
1134 type42->num_glyphs = loader.num_glyphs;
1135
1136 if ( !loader.charstrings.init ) {
1137 FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" ));
1138 error = T42_Err_Invalid_File_Format;
1139 }
1140
1141 loader.charstrings.init = 0;
1142 type42->charstrings_block = loader.charstrings.block;
1143 type42->charstrings = loader.charstrings.elements;
1144 type42->charstrings_len = loader.charstrings.lengths;
1145
1146 /* we copy the glyph names `block' and `elements' fields; */
1147 /* the `lengths' field must be released later */
1148 type42->glyph_names_block = loader.glyph_names.block;
1149 type42->glyph_names = (FT_String**)loader.glyph_names.elements;
1150 loader.glyph_names.block = 0;
1151 loader.glyph_names.elements = 0;
1152
1153 /* we must now build type42.encoding when we have a custom array */
1154 if ( type42->encoding_type == T42_ENCODING_TYPE_ARRAY )
1155 {
1156 FT_Int charcode, idx, min_char, max_char;
1157 FT_Byte* char_name;
1158 FT_Byte* glyph_name;
1159
1160
1161 /* OK, we do the following: for each element in the encoding */
1162 /* table, look up the index of the glyph having the same name */
1163 /* as defined in the CharStrings array. */
1164 /* The index is then stored in type42.encoding.char_index, and */
1165 /* the name in type42.encoding.char_name */
1166
1167 min_char = +32000;
1168 max_char = -32000;
1169
1170 charcode = 0;
1171 for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
1172 {
1173 type42->encoding.char_index[charcode] = 0;
1174 type42->encoding.char_name [charcode] = (char *)".notdef";
1175
1176 char_name = loader.encoding_table.elements[charcode];
1177 if ( char_name )
1178 for ( idx = 0; idx < type42->num_glyphs; idx++ )
1179 {
1180 glyph_name = (FT_Byte*)type42->glyph_names[idx];
1181 if ( ft_strcmp( (const char*)char_name,
1182 (const char*)glyph_name ) == 0 )
1183 {
1184 type42->encoding.char_index[charcode] = (FT_UShort)idx;
1185 type42->encoding.char_name [charcode] = (char*)glyph_name;
1186
1187 /* Change min/max encoded char only if glyph name is */
1188 /* not /.notdef */
1189 if ( ft_strcmp( (const char*)".notdef",
1190 (const char*)glyph_name ) != 0 )
1191 {
1192 if ( charcode < min_char ) min_char = charcode;
1193 if ( charcode > max_char ) max_char = charcode;
1194 }
1195 break;
1196 }
1197 }
1198 }
1199 type42->encoding.code_first = min_char;
1200 type42->encoding.code_last = max_char;
1201 type42->encoding.num_chars = loader.num_chars;
1202 }
1203
1204 Exit:
1205 t42_done_loader( &loader );
1206 return error;
1207 }
1208
1209
1210 /***************** Driver Functions *************/
1211
1212
1213 /*************************************************************************/
1214 /* */
1215 /* <Description> */
1216 /* The face object constructor. */
1217 /* */
1218 /* <Input> */
1219 /* stream :: input stream where to load font data. */
1220 /* */
1221 /* face_index :: The index of the font face in the resource. */
1222 /* */
1223 /* num_params :: Number of additional generic parameters. Ignored. */
1224 /* */
1225 /* params :: Additional generic parameters. Ignored. */
1226 /* */
1227 /* <InOut> */
1228 /* face :: The face record to build. */
1229 /* */
1230 /* <Return> */
1231 /* FreeType error code. 0 means success. */
1232 /* */
1233 static FT_Error
1234 T42_Face_Init( FT_Stream stream,
1235 T42_Face face,
1236 FT_Int face_index,
1237 FT_Int num_params,
1238 FT_Parameter* params)
1239 {
1240 FT_Error error;
1241 PSNames_Service psnames;
1242 PSAux_Service psaux;
1243 FT_Face root = (FT_Face)&face->root;
1244 FT_CharMap charmap = face->charmaprecs;
1245
1246 FT_UNUSED( num_params );
1247 FT_UNUSED( params );
1248 FT_UNUSED( face_index );
1249 FT_UNUSED( stream );
1250
1251
1252 face->ttf_face = NULL;
1253 face->root.num_faces = 1;
1254
1255 /* XXX */
1256 psnames = (PSNames_Service)face->psnames;
1257 if ( !psnames )
1258 {
1259 psnames = (PSNames_Service)
1260 FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
1261 "psnames" );
1262 face->psnames = psnames;
1263 }
1264
1265 psaux = (PSAux_Service)face->psaux;
1266 if ( !psaux )
1267 {
1268 psaux = (PSAux_Service)
1269 FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
1270 "psaux" );
1271 face->psaux = psaux;
1272 }
1273
1274 /* open the tokenizer, this will also check the font format */
1275 error = T42_Open_Face( face );
1276 if ( error )
1277 goto Exit;
1278
1279 /* if we just wanted to check the format, leave successfully now */
1280 if ( face_index < 0 )
1281 goto Exit;
1282
1283 /* check the face index */
1284 if ( face_index != 0 )
1285 {
1286 FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
1287 error = T42_Err_Invalid_Argument;
1288 goto Exit;
1289 }
1290
1291 /* Now, load the font program into the face object */
1292
1293 /* Init the face object fields */
1294 /* Now set up root face fields */
1295
1296 root->num_glyphs = face->type42.num_glyphs;
1297 root->num_charmaps = 1;
1298 root->face_index = face_index;
1299
1300 root->face_flags = FT_FACE_FLAG_SCALABLE;
1301 root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
1302 root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
1303
1304 if ( face->type42.font_info.is_fixed_pitch )
1305 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
1306
1307 /* XXX: TODO -- add kerning with .afm support */
1308
1309 /* get style name -- be careful, some broken fonts only */
1310 /* have a `/FontName' dictionary entry! */
1311 root->family_name = face->type42.font_info.family_name;
1312 if ( root->family_name )
1313 {
1314 char* full = face->type42.font_info.full_name;
1315 char* family = root->family_name;
1316
1317
1318 if ( full )
1319 {
1320 while ( *family && *full == *family )
1321 {
1322 family++;
1323 full++;
1324 }
1325
1326 root->style_name = ( *full == ' ' ? full + 1
1327 : (char *)"Regular" );
1328 }
1329 else
1330 root->style_name = (char *)"Regular";
1331 }
1332 else
1333 {
1334 /* do we have a `/FontName'? */
1335 if ( face->type42.font_name )
1336 {
1337 root->family_name = face->type42.font_name;
1338 root->style_name = (char *)"Regular";
1339 }
1340 }
1341
1342 /* no embedded bitmap support */
1343 root->num_fixed_sizes = 0;
1344 root->available_sizes = 0;
1345
1346 /* Load the TTF font embedded in the T42 font */
1347 error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ),
1348 face->ttf_data,
1349 face->ttf_size,
1350 0,
1351 &face->ttf_face );
1352 if ( error )
1353 goto Exit;
1354
1355 /* Ignore info in FontInfo dictionary and use the info from the */
1356 /* loaded TTF font. The PostScript interpreter also ignores it. */
1357 root->bbox = face->ttf_face->bbox;
1358 root->units_per_EM = face->ttf_face->units_per_EM;
1359
1360 root->ascender = face->ttf_face->ascender;
1361 root->descender = face->ttf_face->descender;
1362 root->height = face->ttf_face->height;
1363
1364 root->max_advance_width = face->ttf_face->max_advance_width;
1365 root->max_advance_height = face->ttf_face->max_advance_height;
1366
1367 root->underline_position = face->type42.font_info.underline_position;
1368 root->underline_thickness = face->type42.font_info.underline_thickness;
1369
1370 root->internal->max_points = 0;
1371 root->internal->max_contours = 0;
1372
1373 /* compute style flags */
1374 root->style_flags = 0;
1375 if ( face->type42.font_info.italic_angle )
1376 root->style_flags |= FT_STYLE_FLAG_ITALIC;
1377
1378 if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
1379 root->style_flags |= FT_STYLE_FLAG_BOLD;
1380
1381 if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
1382 root->face_flags |= FT_FACE_FLAG_VERTICAL;
1383
1384 /* XXX: Add support for new cmaps code in FT 2.1.0 */
1385
1386 /* charmap support -- synthetize unicode charmap if possible */
1387
1388 /* synthesize a Unicode charmap if there is support in the `PSNames' */
1389 /* module */
1390 if ( psnames && psnames->unicode_value )
1391 {
1392 error = psnames->build_unicodes( root->memory,
1393 face->type42.num_glyphs,
1394 (const char**)face->type42.glyph_names,
1395 &face->unicode_map );
1396 if ( !error )
1397 {
1398 root->charmap = charmap;
1399 charmap->face = (FT_Face)face;
1400 charmap->encoding = ft_encoding_unicode;
1401 charmap->platform_id = 3;
1402 charmap->encoding_id = 1;
1403 charmap++;
1404 }
1405
1406 /* XXX: Is the following code correct? It is used in t1objs.c */
1407
1408 /* simply clear the error in case of failure (which really) */
1409 /* means that out of memory or no unicode glyph names */
1410 error = T42_Err_Ok;
1411 }
1412
1413 /* now, support either the standard, expert, or custom encoding */
1414 charmap->face = (FT_Face)face;
1415 charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
1416
1417 switch ( face->type42.encoding_type )
1418 {
1419 case T42_ENCODING_TYPE_STANDARD:
1420 charmap->encoding = ft_encoding_adobe_standard;
1421 charmap->encoding_id = 0;
1422 break;
1423
1424 case T42_ENCODING_TYPE_EXPERT:
1425 charmap->encoding = ft_encoding_adobe_expert;
1426 charmap->encoding_id = 1;
1427 break;
1428
1429 case T42_ENCODING_TYPE_ARRAY:
1430 charmap->encoding = ft_encoding_adobe_custom;
1431 charmap->encoding_id = 2;
1432 break;
1433
1434 case T42_ENCODING_TYPE_ISOLATIN1:
1435 charmap->encoding = ft_encoding_latin_1;
1436 charmap->encoding_id = 3;
1437 break;
1438
1439 default:
1440 FT_ERROR(( "T42_Face_Init: invalid encoding\n" ));
1441 error = T42_Err_Invalid_File_Format;
1442 goto Exit;
1443 }
1444
1445 root->charmaps = face->charmaps;
1446 root->num_charmaps = charmap - face->charmaprecs + 1;
1447 face->charmaps[0] = &face->charmaprecs[0];
1448 face->charmaps[1] = &face->charmaprecs[1];
1449
1450 Exit:
1451 return error;
1452 }
1453
1454
1455 /*************************************************************************/
1456 /* */
1457 /* <Function> */
1458 /* T42_Face_Done */
1459 /* */
1460 /* <Description> */
1461 /* The face object destructor. */
1462 /* */
1463 /* <Input> */
1464 /* face :: A typeless pointer to the face object to destroy. */
1465 /* */
1466 static void
1467 T42_Face_Done( T42_Face face )
1468 {
1469 T42_Font type42;
1470 PS_FontInfo info;
1471 FT_Memory memory;
1472
1473
1474 if ( face )
1475 {
1476 type42 = &face->type42;
1477 info = &type42->font_info;
1478 memory = face->root.memory;
1479
1480 /* delete internal ttf face prior to freeing face->ttf_data */
1481 if ( face->ttf_face )
1482 FT_Done_Face( face->ttf_face );
1483
1484 /* release font info strings */
1485 FT_FREE( info->version );
1486 FT_FREE( info->notice );
1487 FT_FREE( info->full_name );
1488 FT_FREE( info->family_name );
1489 FT_FREE( info->weight );
1490
1491 /* release top dictionary */
1492 FT_FREE( type42->charstrings_len );
1493 FT_FREE( type42->charstrings );
1494 FT_FREE( type42->glyph_names );
1495
1496 FT_FREE( type42->charstrings_block );
1497 FT_FREE( type42->glyph_names_block );
1498
1499 FT_FREE( type42->encoding.char_index );
1500 FT_FREE( type42->encoding.char_name );
1501 FT_FREE( type42->font_name );
1502
1503 FT_FREE( face->ttf_data );
1504
1505#if 0
1506 /* release afm data if present */
1507 if ( face->afm_data )
1508 T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
1509#endif
1510
1511 /* release unicode map, if any */
1512 FT_FREE( face->unicode_map.maps );
1513 face->unicode_map.num_maps = 0;
1514
1515 face->root.family_name = 0;
1516 face->root.style_name = 0;
1517 }
1518 }
1519
1520 /*************************************************************************/
1521 /* */
1522 /* <Function> */
1523 /* T42_Driver_Init */
1524 /* */
1525 /* <Description> */
1526 /* Initializes a given Type 42 driver object. */
1527 /* */
1528 /* <Input> */
1529 /* driver :: A handle to the target driver object. */
1530 /* */
1531 /* <Return> */
1532 /* FreeType error code. 0 means success. */
1533 /* */
1534 static FT_Error
1535 T42_Driver_Init( T42_Driver driver )
1536 {
1537 FT_Module ttmodule;
1538
1539
1540 ttmodule = FT_Get_Module( driver->root.root.library, "truetype" );
1541 driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;
1542
1543 /* XXX: What about hinter support? */
1544#if 0
1545 if (ttmodule->clazz->module_flags & ft_module_driver_has_hinter)
1546 driver->root.clazz->root.module_flags |= ft_module_driver_has_hinter;
1547#endif
1548
1549 return T42_Err_Ok;
1550 }
1551
1552
1553 static void
1554 T42_Driver_Done( T42_Driver driver )
1555 {
1556 FT_UNUSED( driver );
1557 }
1558
1559
1560 /*************************************************************************/
1561 /* */
1562 /* <Function> */
1563 /* Get_Char_Index */
1564 /* */
1565 /* <Description> */
1566 /* Uses a charmap to return a given character code's glyph index. */
1567 /* */
1568 /* <Input> */
1569 /* charmap :: A handle to the source charmap object. */
1570 /* */
1571 /* charcode :: The character code. */
1572 /* */
1573 /* <Return> */
1574 /* Glyph index. 0 means `undefined character code'. */
1575 /* */
1576 static FT_UInt
1577 Get_Char_Index( FT_CharMap charmap,
1578 FT_Long charcode )
1579 {
1580 T42_Face face;
1581 FT_UInt result = 0;
1582 PSNames_Service psnames;
1583
1584
1585 face = (T42_Face)charmap->face;
1586 psnames = (PSNames_Service)face->psnames;
1587 if (!psnames )
1588 goto Exit;
1589
1590 switch ( charmap->encoding )
1591 {
1592 /*******************************************************************/
1593 /* */
1594 /* Unicode encoding support */
1595 /* */
1596 case ft_encoding_unicode:
1597 /* if this charmap is used, we ignore the encoding of the font and */
1598 /* use the `PSNames' module to synthetize the Unicode charmap */
1599 result = psnames->lookup_unicode( &face->unicode_map,
1600 (FT_ULong)charcode );
1601
1602 /* the function returns 0xFFFF if the Unicode charcode has */
1603 /* no corresponding glyph */
1604 if ( result == 0xFFFFU )
1605 result = 0;
1606
1607 /* The result returned is the index (position)in the CharStrings */
1608 /* array. This must be used now to get the value associated to */
1609 /* that glyph_name, which is the real index within the truetype */
1610 /* structure. */
1611 result = ft_atoi( (const char*)face->type42.charstrings[result] );
1612 goto Exit;
1613
1614 /*******************************************************************/
1615 /* */
1616 /* ISOLatin1 encoding support */
1617 /* */
1618 case ft_encoding_latin_1:
1619 /* ISOLatin1 is the first page of Unicode */
1620 if ( charcode < 256 && psnames->unicode_value )
1621 {
1622 result = psnames->lookup_unicode( &face->unicode_map,
1623 (FT_ULong)charcode );
1624
1625 /* the function returns 0xFFFF if the Unicode charcode has */
1626 /* no corresponding glyph */
1627 if ( result == 0xFFFFU )
1628 result = 0;
1629 }
1630 goto Exit;
1631
1632 /*******************************************************************/
1633 /* */
1634 /* Custom Type 1 encoding */
1635 /* */
1636 case ft_encoding_adobe_custom:
1637 {
1638 T1_Encoding encoding = &face->type42.encoding;
1639
1640
1641 if ( charcode >= encoding->code_first &&
1642 charcode <= encoding->code_last )
1643 {
1644 FT_UInt idx = encoding->char_index[charcode];
1645
1646
1647 result = ft_atoi( (const char *)face->type42.charstrings[idx] );
1648 }
1649 goto Exit;
1650 }
1651
1652 /*******************************************************************/
1653 /* */
1654 /* Adobe Standard & Expert encoding support */
1655 /* */
1656 default:
1657 if ( charcode < 256 )
1658 {
1659 FT_UInt code;
1660 FT_Int n;
1661 const char* glyph_name;
1662
1663
1664 code = psnames->adobe_std_encoding[charcode];
1665 if ( charmap->encoding == ft_encoding_adobe_expert )
1666 code = psnames->adobe_expert_encoding[charcode];
1667
1668 glyph_name = psnames->adobe_std_strings( code );
1669 if ( !glyph_name )
1670 break;
1671
1672 for ( n = 0; n < face->type42.num_glyphs; n++ )
1673 {
1674 const char* gname = face->type42.glyph_names[n];
1675
1676 if ( gname && ( ft_strcmp( gname, glyph_name ) == 0 ) )
1677 {
1678 result = ft_atoi( (const char *)face->type42.charstrings[n] );
1679 break;
1680 }
1681 }
1682 }
1683 }
1684
1685 Exit:
1686 return result;
1687 }
1688
1689
1690 static FT_Error
1691 T42_Size_Init( T42_Size size )
1692 {
1693 FT_Face face = size->root.face;
1694 T42_Face t42face = (T42_Face)face;
1695 FT_Size ttsize;
1696 FT_Error error = T42_Err_Ok;
1697
1698
1699 if ( face->size == NULL )
1700 {
1701 /* First size for this face */
1702 size->ttsize = t42face->ttf_face->size;
1703 }
1704 else
1705 {
1706 error = FT_New_Size( t42face->ttf_face, &ttsize );
1707 size->ttsize = ttsize;
1708 }
1709
1710 return error;
1711 }
1712
1713
1714 static void
1715 T42_Size_Done( T42_Size size )
1716 {
1717 FT_Face face = size->root.face;
1718 T42_Face t42face = (T42_Face)face;
1719 FT_ListNode node;
1720
1721
1722 node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );
1723 if ( node )
1724 FT_Done_Size( size->ttsize );
1725 }
1726
1727
1728 static FT_Error
1729 T42_GlyphSlot_Init( T42_GlyphSlot slot )
1730 {
1731 FT_Face face = slot->root.face;
1732 T42_Face t42face = (T42_Face)face;
1733 FT_GlyphSlot ttslot;
1734 FT_Error error = T42_Err_Ok;
1735
1736
1737 if ( face->glyph == NULL )
1738 {
1739 /* First glyph slot for this face */
1740 slot->ttslot = t42face->ttf_face->glyph;
1741 }
1742 else
1743 {
1744 error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
1745 slot->ttslot = ttslot;
1746 }
1747
1748 return error;
1749 }
1750
1751
1752 static void
1753 T42_GlyphSlot_Done( T42_GlyphSlot slot )
1754 {
1755 FT_Face face = slot->root.face;
1756 T42_Face t42face = (T42_Face)face;
1757 FT_GlyphSlot cur = t42face->ttf_face->glyph;
1758
1759
1760 while ( cur )
1761 {
1762 if ( cur == slot->ttslot )
1763 {
1764 FT_Done_GlyphSlot( slot->ttslot );
1765 break;
1766 }
1767
1768 cur = cur->next;
1769 }
1770 }
1771
1772
1773 static FT_Error
1774 T42_Char_Size( T42_Size size,
1775 FT_F26Dot6 char_width,
1776 FT_F26Dot6 char_height,
1777 FT_UInt horz_resolution,
1778 FT_UInt vert_resolution )
1779 {
1780 FT_Face face = size->root.face;
1781 T42_Face t42face = (T42_Face)face;
1782
1783
1784 return FT_Set_Char_Size( t42face->ttf_face,
1785 char_width,
1786 char_height,
1787 horz_resolution,
1788 vert_resolution );
1789 }
1790
1791
1792 static FT_Error
1793 T42_Pixel_Size( T42_Size size,
1794 FT_UInt pixel_width,
1795 FT_UInt pixel_height )
1796 {
1797 FT_Face face = size->root.face;
1798 T42_Face t42face = (T42_Face)face;
1799
1800
1801 return FT_Set_Pixel_Sizes( t42face->ttf_face,
1802 pixel_width,
1803 pixel_height );
1804 }
1805
1806
1807 static void
1808 ft_glyphslot_clear( FT_GlyphSlot slot )
1809 {
1810 /* free bitmap if needed */
1811 if ( slot->flags & FT_GLYPH_OWN_BITMAP )
1812 {
1813 FT_Memory memory = FT_FACE_MEMORY( slot->face );
1814
1815
1816 FT_FREE( slot->bitmap.buffer );
1817 slot->flags &= ~FT_GLYPH_OWN_BITMAP;
1818 }
1819
1820 /* clear all public fields in the glyph slot */
1821 FT_MEM_SET( &slot->metrics, 0, sizeof ( slot->metrics ) );
1822 FT_MEM_SET( &slot->outline, 0, sizeof ( slot->outline ) );
1823 FT_MEM_SET( &slot->bitmap, 0, sizeof ( slot->bitmap ) );
1824
1825 slot->bitmap_left = 0;
1826 slot->bitmap_top = 0;
1827 slot->num_subglyphs = 0;
1828 slot->subglyphs = 0;
1829 slot->control_data = 0;
1830 slot->control_len = 0;
1831 slot->other = 0;
1832 slot->format = ft_glyph_format_none;
1833
1834 slot->linearHoriAdvance = 0;
1835 slot->linearVertAdvance = 0;
1836 }
1837
1838
1839 static FT_Error
1840 T42_Load_Glyph( FT_GlyphSlot glyph,
1841 FT_Size size,
1842 FT_Int glyph_index,
1843 FT_Int load_flags )
1844 {
1845 FT_Error error;
1846 T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph;
1847 T42_Size t42size = (T42_Size)size;
1848 FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;
1849
1850
1851 ft_glyphslot_clear( t42slot->ttslot );
1852 error = ttclazz->load_glyph( t42slot->ttslot,
1853 t42size->ttsize,
1854 glyph_index,
1855 load_flags | FT_LOAD_NO_BITMAP );
1856
1857 if ( !error )
1858 {
1859 glyph->metrics = t42slot->ttslot->metrics;
1860
1861 glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;
1862 glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;
1863
1864 glyph->format = t42slot->ttslot->format;
1865 glyph->outline = t42slot->ttslot->outline;
1866
1867 glyph->bitmap = t42slot->ttslot->bitmap;
1868 glyph->bitmap_left = t42slot->ttslot->bitmap_left;
1869 glyph->bitmap_top = t42slot->ttslot->bitmap_top;
1870 }
1871
1872 return error;
1873 }
1874
1875
1876 /*************************************************************************/
1877 /* */
1878 /* <Function> */
1879 /* Get_Next_Char */
1880 /* */
1881 /* <Description> */
1882 /* Uses a charmap to return the next encoded char. */
1883 /* */
1884 /* <Input> */
1885 /* charmap :: A handle to the source charmap object. */
1886 /* */
1887 /* charcode :: The character code. */
1888 /* */
1889 /* <Return> */
1890 /* Next char code. 0 means `no more char codes'. */
1891 /* */
1892 static FT_Long
1893 Get_Next_Char( FT_CharMap charmap,
1894 FT_Long charcode )
1895 {
1896 T42_Face face;
1897 PSNames_Service psnames;
1898
1899
1900 face = (T42_Face)charmap->face;
1901 psnames = (PSNames_Service)face->psnames;
1902
1903 if ( psnames )
1904 switch ( charmap->encoding )
1905 {
1906 /*******************************************************************/
1907 /* */
1908 /* Unicode encoding support */
1909 /* */
1910 case ft_encoding_unicode:
1911 /* use the `PSNames' module to synthetize the Unicode charmap */
1912 return psnames->next_unicode( &face->unicode_map,
1913 (FT_ULong)charcode );
1914
1915 /*******************************************************************/
1916 /* */
1917 /* ISOLatin1 encoding support */
1918 /* */
1919 case ft_encoding_latin_1:
1920 {
1921 FT_ULong code;
1922
1923
1924 /* use the `PSNames' module to synthetize the Unicode charmap */
1925 code = psnames->next_unicode( &face->unicode_map,
1926 (FT_ULong)charcode );
1927 if ( code < 256 )
1928 return code;
1929 break;
1930 }
1931
1932 /*******************************************************************/
1933 /* */
1934 /* Custom Type 1 encoding */
1935 /* */
1936 case ft_encoding_adobe_custom:
1937 {
1938 T1_Encoding encoding = &face->type42.encoding;
1939
1940
1941 charcode++;
1942 if ( charcode < encoding->code_first )
1943 charcode = encoding->code_first;
1944 while ( charcode <= encoding->code_last ) {
1945 if ( encoding->char_index[charcode] )
1946 return charcode;
1947 charcode++;
1948 }
1949 }
1950
1951
1952 /*******************************************************************/
1953 /* */
1954 /* Adobe Standard & Expert encoding support */
1955 /* */
1956 default:
1957 while ( ++charcode < 256 )
1958 {
1959 FT_UInt code;
1960 FT_Int n;
1961 const char* glyph_name;
1962
1963
1964 code = psnames->adobe_std_encoding[charcode];
1965 if ( charmap->encoding == ft_encoding_adobe_expert )
1966 code = psnames->adobe_expert_encoding[charcode];
1967
1968 glyph_name = psnames->adobe_std_strings( code );
1969 if ( !glyph_name )
1970 continue;
1971
1972 for ( n = 0; n < face->type42.num_glyphs; n++ )
1973 {
1974 const char* gname = face->type42.glyph_names[n];
1975
1976
1977 if ( gname && gname[0] == glyph_name[0] &&
1978 ft_strcmp( gname, glyph_name ) == 0 )
1979 return charcode;
1980 }
1981 }
1982 }
1983
1984 return 0;
1985 }
1986
1987
1988 static FT_Error
1989 t42_get_glyph_name( T42_Face face,
1990 FT_UInt glyph_index,
1991 FT_Pointer buffer,
1992 FT_UInt buffer_max )
1993 {
1994 FT_String* gname;
1995
1996
1997 gname = face->type42.glyph_names[glyph_index];
1998
1999 if ( buffer_max > 0 )
2000 {
2001 FT_UInt len = (FT_UInt)( ft_strlen( gname ) );
2002
2003
2004 if ( len >= buffer_max )
2005 len = buffer_max - 1;
2006 FT_MEM_COPY( buffer, gname, len );
2007 ((FT_Byte*)buffer)[len] = 0;
2008 }
2009
2010 return T42_Err_Ok;
2011 }
2012
2013
2014 static const char*
2015 t42_get_ps_name( T42_Face face )
2016 {
2017 return (const char*)face->type42.font_name;
2018 }
2019
2020
2021 static FT_UInt
2022 t42_get_name_index( T42_Face face,
2023 FT_String* glyph_name )
2024 {
2025 FT_Int i;
2026 FT_String* gname;
2027
2028
2029 for ( i = 0; i < face->type42.num_glyphs; i++ )
2030 {
2031 gname = face->type42.glyph_names[i];
2032
2033 if ( !ft_strcmp( glyph_name, gname ) )
2034 return ft_atoi( (const char *)face->type42.charstrings[i] );
2035 }
2036
2037 return 0;
2038 }
2039
2040
2041 static FT_Module_Interface
2042 Get_Interface( FT_Driver driver,
2043 const FT_String* t42_interface )
2044 {
2045 FT_UNUSED( driver );
2046
2047 /* Any additional interface are defined here */
2048 if (ft_strcmp( (const char*)t42_interface, "glyph_name" ) == 0 )
2049 return (FT_Module_Interface)t42_get_glyph_name;
2050
2051 if ( ft_strcmp( (const char*)t42_interface, "name_index" ) == 0 )
2052 return (FT_Module_Interface)t42_get_name_index;
2053
2054 if ( ft_strcmp( (const char*)t42_interface, "postscript_name" ) == 0 )
2055 return (FT_Module_Interface)t42_get_ps_name;
2056
2057 return 0;
2058 }
2059
2060
2061 const FT_Driver_ClassRec t42_driver_class =
2062 {
2063 {
2064 ft_module_font_driver |
2065 ft_module_driver_scalable |
2066 ft_module_driver_has_hinter,
2067
2068 sizeof ( T42_DriverRec ),
2069
2070 "type42",
2071 0x10000L,
2072 0x20000L,
2073
2074 0, /* format interface */
2075
2076 (FT_Module_Constructor)T42_Driver_Init,
2077 (FT_Module_Destructor) T42_Driver_Done,
2078 (FT_Module_Requester) Get_Interface,
2079 },
2080
2081 sizeof ( T42_FaceRec ),
2082 sizeof ( T42_SizeRec ),
2083 sizeof ( T42_GlyphSlotRec ),
2084
2085 (FT_Face_InitFunc) T42_Face_Init,
2086 (FT_Face_DoneFunc) T42_Face_Done,
2087 (FT_Size_InitFunc) T42_Size_Init,
2088 (FT_Size_DoneFunc) T42_Size_Done,
2089 (FT_Slot_InitFunc) T42_GlyphSlot_Init,
2090 (FT_Slot_DoneFunc) T42_GlyphSlot_Done,
2091
2092 (FT_Size_ResetPointsFunc) T42_Char_Size,
2093 (FT_Size_ResetPixelsFunc) T42_Pixel_Size,
2094 (FT_Slot_LoadFunc) T42_Load_Glyph,
2095 (FT_CharMap_CharIndexFunc)Get_Char_Index,
2096
2097 (FT_Face_GetKerningFunc) 0,
2098 (FT_Face_AttachFunc) 0,
2099
2100 (FT_Face_GetAdvancesFunc) 0,
2101
2102 (FT_CharMap_CharNextFunc) Get_Next_Char
2103 };
2104
2105
2106#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
2107
2108
2109 /*************************************************************************/
2110 /* */
2111 /* <Function> */
2112 /* getDriverClass */
2113 /* */
2114 /* <Description> */
2115 /* This function is used when compiling the TrueType driver as a */
2116 /* shared library (`.DLL' or `.so'). It will be used by the */
2117 /* high-level library of FreeType to retrieve the address of the */
2118 /* driver's generic interface. */
2119 /* */
2120 /* It shouldn't be implemented in a static build, as each driver must */
2121 /* have the same function as an exported entry point. */
2122 /* */
2123 /* <Return> */
2124 /* The address of the T42's driver generic interface. The */
2125 /* format-specific interface can then be retrieved through the method */
2126 /* interface->get_format_interface. */
2127 /* */
2128 FT_EXPORT_DEF( const FT_Driver_Class )
2129 getDriverClass( void )
2130 {
2131 return &t42_driver_class;
2132 }
2133
2134
2135#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
2136
2137
2138/* END */