1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* cidload.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* CID-keyed Type1 font loader (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Copyright 1996-2006, 2009, 2011-2014 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include <ft2build.h> 20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_DEBUG_H 21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_CONFIG_CONFIG_H 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_MULTIPLE_MASTERS_H 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_TYPE1_TYPES_H 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidload.h" 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ciderrs.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_cidload 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* read a single offset */ 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Long ) 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_get_offset( FT_Byte* *start, 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte offsize ) 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong result; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p = *start; 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( result = 0; offsize > 0; offsize-- ) 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result <<= 8; 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result |= *p++; 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *start = p; 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FT_Long)result; 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** TYPE 1 SYMBOL PARSING *****/ 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_load_keyword( CID_Face face, 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Loader* loader, 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const T1_Field keyword ) 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser = &loader->parser; 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* object; 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* dummy_object; 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceInfo cid = &face->cid; 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if the keyword has a dedicated callback, call it */ 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( keyword->type == T1_FIELD_TYPE_CALLBACK ) 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keyword->reader( (FT_Face)face, parser ); 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = parser->root.error; 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we must now compute the address of our target object */ 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( keyword->location ) 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case T1_FIELD_LOCATION_CID_INFO: 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov object = (FT_Byte*)cid; 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case T1_FIELD_LOCATION_FONT_INFO: 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov object = (FT_Byte*)&cid->font_info; 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case T1_FIELD_LOCATION_FONT_EXTRA: 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov object = (FT_Byte*)&face->font_extra; 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case T1_FIELD_LOCATION_BBOX: 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov object = (FT_Byte*)&cid->font_bbox; 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceDict dict; 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts ) 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n", 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keyword->ident )); 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Syntax_Error ); 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict = cid->font_dicts + parser->num_dict; 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( keyword->location ) 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case T1_FIELD_LOCATION_PRIVATE: 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov object = (FT_Byte*)&dict->private_dict; 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov object = (FT_Byte*)dict; 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dummy_object = object; 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now, load the keyword data in the object's field(s) */ 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY || 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keyword->type == T1_FIELD_TYPE_FIXED_ARRAY ) 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_parser_load_field_table( &loader->parser, keyword, 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &dummy_object ); 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_parser_load_field( &loader->parser, 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keyword, &dummy_object ); 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_parse_font_matrix( CID_Face face, 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser ) 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceDict dict; 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Face root = (FT_Face)&face->root; 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed temp[6]; 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed temp_scale; 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_Matrix* matrix; 162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_Vector* offset; 163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_Int result; 164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict = face->cid.font_dicts + parser->num_dict; 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov matrix = &dict->font_matrix; 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = &dict->font_offset; 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov result = cid_parser_to_fixed_array( parser, 6, temp, 3 ); 171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( result < 6 ) 173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_File_Format ); 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp_scale = FT_ABS( temp[3] ); 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( temp_scale == 0 ) 178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_ERROR(( "cid_parse_font_matrix: invalid font matrix\n" )); 180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_File_Format ); 181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set Units per EM based on FontMatrix values. We set the value to */ 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 1000 / temp_scale, because temp_scale was already multiplied by */ 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 1000 (in t1_tofixed, from psobjs.c). */ 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we need to scale the values by 1.0/temp[3] */ 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( temp_scale != 0x10000L ) 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp[0] = FT_DivFix( temp[0], temp_scale ); 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp[1] = FT_DivFix( temp[1], temp_scale ); 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp[2] = FT_DivFix( temp[2], temp_scale ); 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp[4] = FT_DivFix( temp[4], temp_scale ); 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov temp[5] = FT_DivFix( temp[5], temp_scale ); 197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L; 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov matrix->xx = temp[0]; 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov matrix->yx = temp[1]; 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov matrix->xy = temp[2]; 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov matrix->yy = temp[3]; 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* note that the font offsets are expressed in integer font units */ 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset->x = temp[4] >> 16; 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset->y = temp[5] >> 16; 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_Err_Ok; 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parse_fd_array( CID_Face face, 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser ) 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceInfo cid = &face->cid; 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Long num_dicts; 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_dicts = cid_parser_to_int( parser ); 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !cid->font_dicts ) 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) ) 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid->num_dicts = (FT_UInt)num_dicts; 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* don't forget to set a few defaults */ 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < cid->num_dicts; n++ ) 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceDict dict = cid->font_dicts + n; 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* default value for lenIV */ 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict->private_dict.lenIV = 4; 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* by mistake, `expansion_factor' appears both in PS_PrivateRec */ 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and CID_FaceDictRec (both are public header files and can't */ 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* changed); we simply copy the value */ 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CALLBACK_DEF( FT_Error ) 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parse_expansion_factor( CID_Face face, 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser ) 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceDict dict; 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts ) 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict = face->cid.font_dicts + parser->num_dict; 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict->expansion_factor = cid_parser_to_fixed( parser, 0 ); 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dict->private_dict.expansion_factor = dict->expansion_factor; 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const T1_FieldRec cid_field_records[] = 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cidtoken.h" 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T1_FIELD_CALLBACK( "FDArray", parse_fd_array, 0 ) 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T1_FIELD_CALLBACK( "FontMatrix", cid_parse_font_matrix, 0 ) 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 ) 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_parse_dict( CID_Face face, 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Loader* loader, 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* base, 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Long size ) 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser = &loader->parser; 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->root.cursor = base; 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->root.limit = base + size; 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->root.error = FT_Err_Ok; 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* cur = base; 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* limit = cur + size; 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (;;) 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* newlimit; 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->root.cursor = cur; 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_parser_skip_spaces( parser ); 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->root.cursor >= limit ) 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov newlimit = limit - 1 - 17; 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov newlimit = parser->root.cursor - 17; 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* look for `%ADOBeginFontDict' */ 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; cur < newlimit; cur++ ) 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( *cur == '%' && 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 ) 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if /FDArray was found, then cid->num_dicts is > 0, and */ 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we can start increasing parser->num_dict */ 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->cid.num_dicts > 0 ) 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->num_dict++; 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cur = parser->root.cursor; 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no error can occur in cid_parser_skip_spaces */ 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cur >= limit ) 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_parser_skip_PS_token( parser ); 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->root.cursor >= limit || parser->root.error ) 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* look for immediates */ 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( *cur == '/' && cur + 2 < limit ) 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_PtrDist len; 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cur++; 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len = parser->root.cursor - cur; 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( len > 0 && len < 22 ) 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now compare the immediate name to the keyword table */ 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov T1_Field keyword = (T1_Field)cid_field_records; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (;;) 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* name; 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov name = (FT_Byte*)keyword->ident; 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !name ) 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cur[0] == name[0] && 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len == (FT_PtrDist)ft_strlen( (const char*)name ) ) 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_PtrDist n; 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 1; n < len; n++ ) 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cur[n] != name[n] ) 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n >= len ) 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we found it - run the parsing callback */ 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->root.error = cid_load_keyword( face, 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov loader, 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keyword ); 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->root.error ) 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return parser->root.error; 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov keyword++; 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cur = parser->root.cursor; 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return parser->root.error; 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* read the subrmap and the subrs of each font dict */ 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_read_subrs( CID_Face face ) 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceInfo cid = &face->cid; 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = face->cid_stream; 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Subrs subr; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt max_offsets = 0; 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong* offsets = 0; 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PSAux_Service psaux = (PSAux_Service)face->psaux; 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) ) 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subr = face->subrs; 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < cid->num_dicts; n++, subr++ ) 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_FaceDict dict = cid->font_dicts + n; 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int lenIV = dict->private_dict.lenIV; 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt count, num_subrs = dict->num_subrs; 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong data_len; 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte* p; 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Check for possible overflow. */ 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_subrs == FT_UINT_MAX ) 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Syntax_Error ); 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reallocate offsets array if needed */ 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_subrs + 1 > max_offsets ) 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 ); 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( new_max <= max_offsets ) 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Syntax_Error ); 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) ) 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max_offsets = new_max; 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* read the subrmap's offsets */ 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) || 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) ) 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = (FT_Byte*)stream->cursor; 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 0; count <= num_subrs; count++ ) 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes ); 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* offsets must be ordered */ 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 1; count <= num_subrs; count++ ) 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( offsets[count - 1] > offsets[count] ) 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now, compute the size of subrs charstrings, */ 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* allocate, and read them */ 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data_len = offsets[num_subrs] - offsets[0]; 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) || 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ALLOC( subr->code[0], data_len ) ) 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) || 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_STREAM_READ( subr->code[0], data_len ) ) 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* set up pointers */ 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 1; count <= num_subrs; count++ ) 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong len; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len = offsets[count] - offsets[count - 1]; 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subr->code[count] = subr->code[count - 1] + len; 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* decrypt subroutines, but only if lenIV >= 0 */ 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( lenIV >= 0 ) 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( count = 0; count < num_subrs; count++ ) 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong len; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len = offsets[count + 1] - offsets[count]; 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov psaux->t1_decrypt( subr->code[count], len, 4330 ); 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov subr->num_subrs = num_subrs; 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( offsets ); 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail: 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->subrs ) 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < cid->num_dicts; n++ ) 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->subrs[n].code ) 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( face->subrs[n].code[0] ); 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( face->subrs[n].code ); 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( face->subrs ); 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_init_loader( CID_Loader* loader, 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Face face ) 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( face ); 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_ZERO( loader, sizeof ( *loader ) ); 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_done_loader( CID_Loader* loader ) 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser = &loader->parser; 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* finalize parser */ 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_parser_done( parser ); 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_hex_to_binary( FT_Byte* data, 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Long data_len, 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong offset, 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Face face ) 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = face->root.stream; 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte buffer[256]; 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte *p, *plimit; 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte *d, *dlimit; 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Byte val; 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool upper_nibble, done; 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( offset ) ) 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d = data; 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dlimit = d + data_len; 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = buffer; 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov plimit = p; 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upper_nibble = 1; 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov done = 0; 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( d < dlimit ) 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( p >= plimit ) 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong oldpos = FT_STREAM_POS(); 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong size = stream->size - oldpos; 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( size == 0 ) 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Syntax_Error ); 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) ) 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = buffer; 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov plimit = p + FT_STREAM_POS() - oldpos; 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ft_isdigit( *p ) ) 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Byte)( *p - '0' ); 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( *p >= 'a' && *p <= 'f' ) 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Byte)( *p - 'a' ); 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( *p >= 'A' && *p <= 'F' ) 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Byte)( *p - 'A' + 10 ); 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( *p == ' ' || 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p == '\t' || 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p == '\r' || 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p == '\n' || 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p == '\f' || 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p == '\0' ) 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p++; 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( *p == '>' ) 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = 0; 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov done = 1; 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Syntax_Error ); 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( upper_nibble ) 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *d = (FT_Byte)( val << 4 ); 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *d = (FT_Byte)( *d + val ); 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d++; 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upper_nibble = (FT_Byte)( 1 - upper_nibble ); 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( done ) 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p++; 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_face_open( CID_Face face, 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int face_index ) 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Loader loader; 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CID_Parser* parser; 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_init_loader( &loader, face ); 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser = &loader.parser; 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_parser_new( parser, face->root.stream, face->root.memory, 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (PSAux_Service)face->psaux ); 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_parse_dict( face, &loader, 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->postscript, 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->postscript_len ); 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face_index < 0 ) 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW( face->cid_stream ) ) 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( parser->binary_length ) 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we must convert the data section from hexadecimal to binary */ 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_ALLOC( face->binary_data, parser->binary_length ) || 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_hex_to_binary( face->binary_data, parser->binary_length, 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parser->data_offset, face ) ) 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_OpenMemory( face->cid_stream, 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->binary_data, parser->binary_length ); 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->cid.data_offset = 0; 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *face->cid_stream = *face->root.stream; 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->cid.data_offset = loader.parser.data_offset; 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = cid_read_subrs( face ); 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cid_done_loader( &loader ); 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 702