21#include FT_CONFIG_CONFIG_H
38#define FT_COMPONENT cidload
42 FT_LOCAL_DEF( FT_ULong )
43 cid_get_offset( FT_Byte* *start,
50 for ( result = 0; offsize > 0; offsize-- )
71 cid_load_keyword( CID_Face face,
73 const T1_Field keyword )
76 CID_Parser* parser = &loader->parser;
79 CID_FaceInfo cid = &face->cid;
83 if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
85 FT_TRACE4((
" %s", keyword->ident ));
87 keyword->reader( (FT_Face)face, parser );
88 error = parser->root.error;
93 switch ( keyword->location )
95 case T1_FIELD_LOCATION_CID_INFO:
96 object = (FT_Byte*)cid;
99 case T1_FIELD_LOCATION_FONT_INFO:
100 object = (FT_Byte*)&cid->font_info;
103 case T1_FIELD_LOCATION_FONT_EXTRA:
104 object = (FT_Byte*)&face->font_extra;
107 case T1_FIELD_LOCATION_BBOX:
108 object = (FT_Byte*)&cid->font_bbox;
116 if ( parser->num_dict >= cid->num_dicts )
118 FT_ERROR((
"cid_load_keyword: invalid use of `%s'\n",
120 error = FT_THROW( Syntax_Error );
124 dict = cid->font_dicts + parser->num_dict;
125 switch ( keyword->location )
127 case T1_FIELD_LOCATION_PRIVATE:
128 object = (FT_Byte*)&dict->private_dict;
132 object = (FT_Byte*)dict;
137 FT_TRACE4((
" %s", keyword->ident ));
139 dummy_object = object;
142 if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
143 keyword->type == T1_FIELD_TYPE_FIXED_ARRAY )
144 error = cid_parser_load_field_table( &loader->parser, keyword,
147 error = cid_parser_load_field( &loader->parser,
148 keyword, &dummy_object );
157 FT_CALLBACK_DEF(
void )
158 cid_parse_font_matrix( FT_Face face,
161 CID_Face cidface = (CID_Face)face;
162 CID_Parser* parser = (CID_Parser*)parser_;
168 if ( parser->num_dict < cidface->cid.num_dicts )
175 dict = cidface->cid.font_dicts + parser->num_dict;
176 matrix = &dict->font_matrix;
177 offset = &dict->font_offset;
180 result = cid_parser_to_fixed_array( parser, 6, temp, 3 );
184 FT_ERROR((
"cid_parse_font_matrix: not enough matrix elements\n" ));
188 FT_TRACE4((
" [%f %f %f %f %f %f]\n",
189 (
double)temp[0] / 65536 / 1000,
190 (
double)temp[1] / 65536 / 1000,
191 (
double)temp[2] / 65536 / 1000,
192 (
double)temp[3] / 65536 / 1000,
193 (
double)temp[4] / 65536 / 1000,
194 (
double)temp[5] / 65536 / 1000 ));
196 temp_scale = FT_ABS( temp[3] );
198 if ( temp_scale == 0 )
200 FT_ERROR((
"cid_parse_font_matrix: invalid font matrix\n" ));
205 if ( temp_scale != 0x10000L )
208 face->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
210 temp[0] = FT_DivFix( temp[0], temp_scale );
211 temp[1] = FT_DivFix( temp[1], temp_scale );
212 temp[2] = FT_DivFix( temp[2], temp_scale );
213 temp[4] = FT_DivFix( temp[4], temp_scale );
214 temp[5] = FT_DivFix( temp[5], temp_scale );
215 temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
218 matrix->xx = temp[0];
219 matrix->yx = temp[1];
220 matrix->xy = temp[2];
221 matrix->yy = temp[3];
223 if ( !FT_Matrix_Check( matrix ) )
225 FT_ERROR((
"t1_parse_font_matrix: invalid font matrix\n" ));
226 parser->root.error = FT_THROW( Invalid_File_Format );
231 offset->x = temp[4] >> 16;
232 offset->y = temp[5] >> 16;
240 FT_CALLBACK_DEF(
void )
241 parse_fd_array( FT_Face face,
244 CID_Face cidface = (CID_Face)face;
245 CID_Parser* parser = (CID_Parser*)parser_;
246 CID_FaceInfo cid = &cidface->cid;
247 FT_Memory memory = FT_FACE_MEMORY( face );
248 FT_Stream stream = parser->stream;
249 FT_Error error = FT_Err_Ok;
250 FT_Long num_dicts, max_dicts;
253 num_dicts = cid_parser_to_int( parser );
254 if ( num_dicts < 0 || num_dicts > FT_INT_MAX )
256 FT_ERROR((
"parse_fd_array: invalid number of dictionaries\n" ));
260 FT_TRACE4((
" %ld\n", num_dicts ));
278 max_dicts = (FT_Long)( stream->size / 100 );
279 if ( num_dicts > max_dicts )
281 FT_TRACE0((
"parse_fd_array: adjusting FDArray size"
282 " (from %ld to %ld)\n",
283 num_dicts, max_dicts ));
284 num_dicts = max_dicts;
287 if ( !cid->font_dicts )
292 if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
295 cid->num_dicts = num_dicts;
298 for ( n = 0; n < cid->num_dicts; n++ )
300 CID_FaceDict dict = cid->font_dicts + n;
303 dict->private_dict.blue_shift = 7;
304 dict->private_dict.blue_fuzz = 1;
305 dict->private_dict.lenIV = 4;
306 dict->private_dict.expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
307 dict->private_dict.blue_scale = (FT_Fixed)(
308 0.039625 * 0x10000L * 1000 );
321 FT_CALLBACK_DEF(
void )
322 parse_expansion_factor( FT_Face face,
325 CID_Face cidface = (CID_Face)face;
326 CID_Parser* parser = (CID_Parser*)parser_;
330 if ( parser->num_dict < cidface->cid.num_dicts )
332 dict = cidface->cid.font_dicts + parser->num_dict;
334 dict->expansion_factor = cid_parser_to_fixed( parser, 0 );
335 dict->private_dict.expansion_factor = dict->expansion_factor;
337 FT_TRACE4((
"%ld\n", dict->expansion_factor ));
348 FT_CALLBACK_DEF(
void )
349 parse_font_name( FT_Face face,
352#ifdef FT_DEBUG_LEVEL_TRACE
353 CID_Face cidface = (CID_Face)face;
354 CID_Parser* parser = (CID_Parser*)parser_;
357 if ( parser->num_dict < cidface->cid.num_dicts )
363 cid_parser_to_token( parser, &token );
365 len = (FT_UInt)( token.limit - token.start );
367 FT_TRACE4((
" %.*s\n", len, token.start ));
369 FT_TRACE4((
" <no value>\n" ));
373 FT_UNUSED( parser_ );
381 const T1_FieldRec cid_field_records[] =
386 T1_FIELD_CALLBACK(
"FDArray", parse_fd_array, 0 )
387 T1_FIELD_CALLBACK(
"FontMatrix", cid_parse_font_matrix, 0 )
388 T1_FIELD_CALLBACK(
"ExpansionFactor", parse_expansion_factor, 0 )
389 T1_FIELD_CALLBACK(
"FontName", parse_font_name, 0 )
396 cid_parse_dict( CID_Face face,
401 CID_Parser* parser = &loader->parser;
404 parser->root.cursor = base;
405 parser->root.limit = base + size;
406 parser->root.error = FT_Err_Ok;
410 FT_Byte* limit = cur + size;
418 parser->root.cursor = cur;
419 cid_parser_skip_spaces( parser );
421 if ( parser->root.cursor >= limit )
422 newlimit = limit - 1 - 17;
424 newlimit = parser->root.cursor - 17;
427 for ( ; cur < newlimit; cur++ )
430 ft_strncmp( (
char*)cur,
"%ADOBeginFontDict", 17 ) == 0 )
434 if ( face->cid.num_dicts > 0 )
438#ifdef FT_DEBUG_LEVEL_TRACE
439 FT_TRACE4((
" FontDict %u", parser->num_dict ));
440 if ( parser->num_dict > face->cid.num_dicts )
441 FT_TRACE4((
" (ignored)" ));
448 cur = parser->root.cursor;
453 cid_parser_skip_PS_token( parser );
454 if ( parser->root.cursor >= limit || parser->root.error )
458 if ( *cur ==
'/' && cur + 2 < limit )
464 len = (FT_UInt)( parser->root.cursor - cur );
466 if ( len > 0 && len < 22 )
469 T1_Field keyword = (T1_Field)cid_field_records;
472 while ( keyword->len )
474 FT_Byte* name = (FT_Byte*)keyword->ident;
477 if ( keyword->len == len &&
478 ft_memcmp( cur, name, len ) == 0 )
481 parser->root.error = cid_load_keyword( face,
484 if ( parser->root.error )
485 return parser->root.error;
494 cur = parser->root.cursor;
497 if ( !face->cid.num_dicts )
499 FT_ERROR((
"cid_parse_dict: No font dictionary found\n" ));
500 return FT_THROW( Invalid_File_Format );
504 return parser->root.error;
510 cid_read_subrs( CID_Face face )
512 CID_FaceInfo cid = &face->cid;
513 FT_Memory memory = face->root.memory;
514 FT_Stream stream = face->cid_stream;
518 FT_UInt max_offsets = 0;
519 FT_ULong* offsets = NULL;
520 PSAux_Service psaux = (PSAux_Service)face->psaux;
523 if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
527 for ( n = 0; n < cid->num_dicts; n++, subr++ )
529 CID_FaceDict dict = cid->font_dicts + n;
530 FT_Int lenIV = dict->private_dict.lenIV;
531 FT_UInt count, num_subrs = dict->num_subrs;
540 if ( num_subrs + 1 > max_offsets )
542 FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
545 if ( new_max <= max_offsets )
547 error = FT_THROW( Syntax_Error );
551 if ( FT_QRENEW_ARRAY( offsets, max_offsets, new_max ) )
554 max_offsets = new_max;
558 if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
559 FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) )
562 p = (FT_Byte*)stream->cursor;
563 for ( count = 0; count <= num_subrs; count++ )
564 offsets[count] = cid_get_offset( &p, dict->sd_bytes );
569 for ( count = 1; count <= num_subrs; count++ )
570 if ( offsets[count - 1] > offsets[count] )
572 FT_ERROR((
"cid_read_subrs: offsets are not ordered\n" ));
573 error = FT_THROW( Invalid_File_Format );
577 if ( offsets[num_subrs] > stream->size - cid->data_offset )
579 FT_ERROR((
"cid_read_subrs: too large `subrs' offsets\n" ));
580 error = FT_THROW( Invalid_File_Format );
586 data_len = offsets[num_subrs] - offsets[0];
588 if ( FT_QNEW_ARRAY( subr->code, num_subrs + 1 ) ||
589 FT_QALLOC( subr->code[0], data_len ) )
592 if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
593 FT_STREAM_READ( subr->code[0], data_len ) )
597 for ( count = 1; count <= num_subrs; count++ )
602 len = offsets[count] - offsets[count - 1];
603 subr->code[count] = subr->code[count - 1] + len;
609 for ( count = 0; count < num_subrs; count++ )
614 len = offsets[count + 1] - offsets[count];
615 psaux->t1_decrypt( subr->code[count], len, 4330 );
619 subr->num_subrs = (FT_Int)num_subrs;
629 for ( n = 0; n < cid->num_dicts; n++ )
631 if ( face->subrs[n].code )
632 FT_FREE( face->subrs[n].code[0] );
634 FT_FREE( face->subrs[n].code );
636 FT_FREE( face->subrs );
643 cid_init_loader( CID_Loader* loader,
653 cid_done_loader( CID_Loader* loader )
655 CID_Parser* parser = &loader->parser;
659 cid_parser_done( parser );
664 cid_hex_to_binary( FT_Byte* data,
668 FT_ULong* data_written )
670 FT_Stream stream = face->root.stream;
675 FT_Byte *d = data, *dlimit;
678 FT_Bool upper_nibble, done;
681 if ( FT_STREAM_SEEK( offset ) )
684 dlimit = d + data_len;
695 FT_ULong oldpos = FT_STREAM_POS();
696 FT_ULong size = stream->size - oldpos;
701 error = FT_THROW( Syntax_Error );
705 if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
708 plimit = p + FT_STREAM_POS() - oldpos;
711 if ( ft_isdigit( *p ) )
712 val = (FT_Byte)( *p -
'0' );
713 else if ( *p >=
'a' && *p <=
'f' )
714 val = (FT_Byte)( *p -
'a' + 10 );
715 else if ( *p >=
'A' && *p <=
'F' )
716 val = (FT_Byte)( *p -
'A' + 10 );
717 else if ( *p ==
' ' ||
727 else if ( *p ==
'>' )
734 error = FT_THROW( Syntax_Error );
739 *d = (FT_Byte)( val << 4 );
742 *d = (FT_Byte)( *d + val );
746 upper_nibble = (FT_Byte)( 1 - upper_nibble );
757 *data_written = (FT_ULong)( d - data );
762 FT_LOCAL_DEF( FT_Error )
763 cid_face_open( CID_Face face,
768 FT_Memory memory = face->root.memory;
772 CID_FaceInfo cid = &face->cid;
774 FT_ULong binary_length;
777 cid_init_loader( &loader, face );
779 parser = &loader.parser;
780 error = cid_parser_new( parser, face->root.stream, face->root.memory,
781 (PSAux_Service)face->psaux );
785 error = cid_parse_dict( face, &loader,
787 parser->postscript_len );
791 if ( face_index < 0 )
794 if ( FT_NEW( face->cid_stream ) )
797 if ( parser->binary_length )
799 if ( parser->binary_length >
800 face->root.stream->size - parser->data_offset )
802 FT_TRACE0((
"cid_face_open: adjusting length of binary data\n" ));
803 FT_TRACE0((
" (from %lu to %lu bytes)\n",
804 parser->binary_length,
805 face->root.stream->size - parser->data_offset ));
806 parser->binary_length = face->root.stream->size -
811 if ( FT_QALLOC( face->binary_data, parser->binary_length ) ||
812 FT_SET_ERROR( cid_hex_to_binary( face->binary_data,
813 parser->binary_length,
819 FT_Stream_OpenMemory( face->cid_stream,
820 face->binary_data, binary_length );
821 cid->data_offset = 0;
825 *face->cid_stream = *face->root.stream;
826 cid->data_offset = loader.parser.data_offset;
831 if ( cid->gd_bytes == 0 )
833 FT_ERROR((
"cid_face_open:"
834 " Invalid `GDBytes' value\n" ));
835 error = FT_THROW( Invalid_File_Format );
840 if ( cid->fd_bytes > 4 || cid->gd_bytes > 4 )
842 FT_ERROR((
"cid_face_open:"
843 " Values of `FDBytes' or `GDBytes' larger than 4\n" ));
845 " are not supported\n" ));
846 error = FT_THROW( Invalid_File_Format );
850 binary_length = face->cid_stream->size - cid->data_offset;
852 if ( cid->cidmap_offset > binary_length )
854 FT_ERROR((
"cid_face_open: Invalid `CIDMapOffset' value\n" ));
855 error = FT_THROW( Invalid_File_Format );
860 if ( cid->cid_count > FT_ULONG_MAX / 8 ||
861 cid->cid_count * ( cid->fd_bytes + cid->gd_bytes ) >
862 binary_length - cid->cidmap_offset )
864 FT_ERROR((
"cid_face_open: Invalid `CIDCount' value\n" ));
865 error = FT_THROW( Invalid_File_Format );
870 for ( n = 0; n < cid->num_dicts; n++ )
872 CID_FaceDict dict = cid->font_dicts + n;
876 if ( dict->private_dict.blue_shift > 1000 ||
877 dict->private_dict.blue_shift < 0 )
879 FT_TRACE2((
"cid_face_open:"
880 " setting unlikely BlueShift value %d to default (7)\n",
881 dict->private_dict.blue_shift ));
882 dict->private_dict.blue_shift = 7;
885 if ( dict->private_dict.blue_fuzz > 1000 ||
886 dict->private_dict.blue_fuzz < 0 )
888 FT_TRACE2((
"cid_face_open:"
889 " setting unlikely BlueFuzz value %d to default (1)\n",
890 dict->private_dict.blue_fuzz ));
891 dict->private_dict.blue_fuzz = 1;
894 if ( dict->num_subrs && dict->sd_bytes == 0 )
896 FT_ERROR((
"cid_face_open: Invalid `SDBytes' value\n" ));
897 error = FT_THROW( Invalid_File_Format );
901 if ( dict->sd_bytes > 4 )
903 FT_ERROR((
"cid_face_open:"
904 " Values of `SDBytes' larger than 4"
905 " are not supported\n" ));
906 error = FT_THROW( Invalid_File_Format );
910 if ( dict->subrmap_offset > binary_length )
912 FT_ERROR((
"cid_face_open: Invalid `SubrMapOffset' value\n" ));
913 error = FT_THROW( Invalid_File_Format );
918 if ( dict->num_subrs > FT_UINT_MAX / 4 ||
919 dict->num_subrs * dict->sd_bytes >
920 binary_length - dict->subrmap_offset )
922 FT_ERROR((
"cid_face_open: Invalid `SubrCount' value\n" ));
923 error = FT_THROW( Invalid_File_Format );
929 error = cid_read_subrs( face );
932 cid_done_loader( &loader );