T42_Face_Init( FT_Stream stream, FT_Face t42face, /* T42_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { T42_Face face = (T42_Face)t42face; FT_Error error; FT_Service_PsCMaps psnames; PSAux_Service psaux; FT_Face root = (FT_Face)&face->root; T1_Font type1 = &face->type1; PS_FontInfo info = &type1->font_info; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( face_index ); FT_UNUSED( stream ); face->ttf_face = NULL; face->root.num_faces = 1; FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); face->psnames = psnames; face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); psaux = (PSAux_Service)face->psaux; if ( !psaux ) { FT_ERROR(( "T42_Face_Init: cannot access `psaux' module\n" )); error = T42_Err_Missing_Module; goto Exit; } FT_TRACE2(( "Type 42 driver\n" )); /* open the tokenizer, this will also check the font format */ error = T42_Open_Face( face ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ if ( face_index > 0 ) { FT_ERROR(( "T42_Face_Init: invalid face index\n" )); error = T42_Err_Invalid_Argument; goto Exit; } /* Now load the font program into the face object */ /* Init the face object fields */ /* Now set up root face fields */ root->num_glyphs = type1->num_glyphs; root->num_charmaps = 0; root->face_index = 0; root->face_flags = FT_FACE_FLAG_SCALABLE | FT_FACE_FLAG_HORIZONTAL | FT_FACE_FLAG_GLYPH_NAMES; if ( info->is_fixed_pitch ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* We only set this flag if we have the patented bytecode interpreter. */ /* There are no known `tricky' Type42 fonts that could be loaded with */ /* the unpatented interpreter. */ #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER root->face_flags |= FT_FACE_FLAG_HINTER; #endif /* XXX: TODO -- add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ /* have a `/FontName' dictionary entry! */ root->family_name = info->family_name; /* assume "Regular" style if we don't know better */ root->style_name = (char *)"Regular"; if ( root->family_name ) { char* full = info->full_name; char* family = root->family_name; if ( full ) { while ( *full ) { if ( *full == *family ) { family++; full++; } else { if ( *full == ' ' || *full == '-' ) full++; else if ( *family == ' ' || *family == '-' ) family++; else { if ( !*family ) root->style_name = full; break; } } } } } else { /* do we have a `/FontName'? */ if ( type1->font_name ) root->family_name = type1->font_name; } /* no embedded bitmap support */ root->num_fixed_sizes = 0; root->available_sizes = 0; /* Load the TTF font embedded in the T42 font */ { FT_Open_Args args; args.flags = FT_OPEN_MEMORY; args.memory_base = face->ttf_data; args.memory_size = face->ttf_size; if ( num_params ) { args.flags |= FT_OPEN_PARAMS; args.num_params = num_params; args.params = params; } error = FT_Open_Face( FT_FACE_LIBRARY( face ), &args, 0, &face->ttf_face ); } if ( error ) goto Exit; FT_Done_Size( face->ttf_face->size ); /* Ignore info in FontInfo dictionary and use the info from the */ /* loaded TTF font. The PostScript interpreter also ignores it. */ root->bbox = face->ttf_face->bbox; root->units_per_EM = face->ttf_face->units_per_EM; root->ascender = face->ttf_face->ascender; root->descender = face->ttf_face->descender; root->height = face->ttf_face->height; root->max_advance_width = face->ttf_face->max_advance_width; root->max_advance_height = face->ttf_face->max_advance_height; root->underline_position = (FT_Short)info->underline_position; root->underline_thickness = (FT_Short)info->underline_thickness; /* compute style flags */ root->style_flags = 0; if ( info->italic_angle ) root->style_flags |= FT_STYLE_FLAG_ITALIC; if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) root->style_flags |= FT_STYLE_FLAG_BOLD; if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) root->face_flags |= FT_FACE_FLAG_VERTICAL; { if ( psnames ) { FT_CharMapRec charmap; T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; FT_CMap_Class clazz; charmap.face = root; /* first of all, try to synthesize a Unicode charmap */ charmap.platform_id = TT_PLATFORM_MICROSOFT; charmap.encoding_id = TT_MS_ID_UNICODE_CS; charmap.encoding = FT_ENCODING_UNICODE; error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); if ( error && FT_Err_No_Unicode_Glyph_Name != error ) goto Exit; error = FT_Err_Ok; /* now, generate an Adobe Standard encoding when appropriate */ charmap.platform_id = TT_PLATFORM_ADOBE; clazz = NULL; switch ( type1->encoding_type ) { case T1_ENCODING_TYPE_STANDARD: charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.encoding_id = TT_ADOBE_ID_STANDARD; clazz = cmap_classes->standard; break; case T1_ENCODING_TYPE_EXPERT: charmap.encoding = FT_ENCODING_ADOBE_EXPERT; charmap.encoding_id = TT_ADOBE_ID_EXPERT; clazz = cmap_classes->expert; break; case T1_ENCODING_TYPE_ARRAY: charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; charmap.encoding_id = TT_ADOBE_ID_CUSTOM; clazz = cmap_classes->custom; break; case T1_ENCODING_TYPE_ISOLATIN1: charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; charmap.encoding_id = TT_ADOBE_ID_LATIN_1; clazz = cmap_classes->unicode; break; default: ; } if ( clazz ) error = FT_CMap_New( clazz, NULL, &charmap, NULL ); #if 0 /* Select default charmap */ if ( root->num_charmaps ) root->charmap = root->charmaps[0]; #endif } } Exit: return error; }
cff_face_init( FT_Stream stream, FT_Face cffface, /* CFF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { CFF_Face face = (CFF_Face)cffface; FT_Error error; SFNT_Service sfnt; FT_Service_PsCMaps psnames; PSHinter_Service pshinter; FT_Bool pure_cff = 1; FT_Bool sfnt_format = 0; FT_Library library = cffface->driver->root.library; sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) { FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" )); error = CFF_Err_Missing_Module; goto Exit; } FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); pshinter = (PSHinter_Service)FT_Get_Module_Interface( library, "pshinter" ); FT_TRACE2(( "CFF driver\n" )); /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; /* check whether we have a valid OpenType file */ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ { FT_TRACE2(( " not an OpenType/CFF font\n" )); error = CFF_Err_Unknown_File_Format; goto Exit; } /* if we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) return CFF_Err_Ok; /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */ if ( face_index > 0 ) { FT_ERROR(( "cff_face_init: invalid face index\n" )); error = CFF_Err_Invalid_Argument; goto Exit; } sfnt_format = 1; /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ /* font; in the latter case it doesn't have a `head' table */ error = face->goto_table( face, TTAG_head, stream, 0 ); if ( !error ) { pure_cff = 0; /* load font directory */ error = sfnt->load_face( stream, face, 0, num_params, params ); if ( error ) goto Exit; } else { /* load the `cmap' table explicitly */ error = sfnt->load_cmap( face, stream ); if ( error ) goto Exit; /* XXX: we don't load the GPOS table, as OpenType Layout */ /* support will be added later to a layout library on top of */ /* FreeType 2 */ } /* now load the CFF part of the file */ error = face->goto_table( face, TTAG_CFF, stream, 0 ); if ( error ) goto Exit; } else { /* rewind to start of file; we are going to load a pure-CFF font */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; error = CFF_Err_Ok; } /* now load and parse the CFF table in the file */ { CFF_Font cff = NULL; CFF_FontRecDict dict; FT_Memory memory = cffface->memory; FT_Int32 flags; FT_UInt i; if ( FT_NEW( cff ) ) goto Exit; face->extra.data = cff; error = cff_font_load( library, stream, face_index, cff, pure_cff ); if ( error ) goto Exit; cff->pshinter = pshinter; cff->psnames = psnames; cffface->face_index = face_index; /* Complement the root flags with some interesting information. */ /* Note that this is only necessary for pure CFF and CEF fonts; */ /* SFNT based fonts use the `name' table instead. */ cffface->num_glyphs = cff->num_glyphs; dict = &cff->top_font.font_dict; /* we need the `PSNames' module for CFF and CEF formats */ /* which aren't CID-keyed */ if ( dict->cid_registry == 0xFFFFU && !psnames ) { FT_ERROR(( "cff_face_init:" " cannot open CFF & CEF fonts\n" " " " without the `PSNames' module\n" )); error = CFF_Err_Missing_Module; goto Exit; } #ifdef FT_DEBUG_LEVEL_TRACE { FT_UInt idx; FT_String* s; FT_TRACE4(( "SIDs\n" )); /* dump string index, including default strings for convenience */ for ( idx = 0; idx < cff->num_strings + 390; idx++ ) { s = cff_index_get_sid_string( cff, idx ); if ( s ) FT_TRACE4((" %5d %s\n", idx, s )); } } #endif /* FT_DEBUG_LEVEL_TRACE */ if ( !dict->has_font_matrix ) dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; /* Normalize the font matrix so that `matrix->xx' is 1; the */ /* scaling is done with `units_per_em' then (at this point, */ /* it already contains the scaling factor, but without */ /* normalization of the matrix). */ /* */ /* Note that the offsets must be expressed in integer font */ /* units. */ { FT_Matrix* matrix = &dict->font_matrix; FT_Vector* offset = &dict->font_offset; FT_ULong* upm = &dict->units_per_em; FT_Fixed temp = FT_ABS( matrix->yy ); if ( temp != 0x10000L ) { *upm = FT_DivFix( *upm, temp ); matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp ); matrix->yy = FT_DivFix( matrix->yy, temp ); offset->x = FT_DivFix( offset->x, temp ); offset->y = FT_DivFix( offset->y, temp ); } offset->x >>= 16; offset->y >>= 16; } for ( i = cff->num_subfonts; i > 0; i-- ) { CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; CFF_FontRecDict top = &cff->top_font.font_dict; FT_Matrix* matrix; FT_Vector* offset; FT_ULong* upm; FT_Fixed temp; if ( sub->has_font_matrix ) { FT_Long scaling; /* if we have a top-level matrix, */ /* concatenate the subfont matrix */ if ( top->has_font_matrix ) { if ( top->units_per_em > 1 && sub->units_per_em > 1 ) scaling = FT_MIN( top->units_per_em, sub->units_per_em ); else scaling = 1; FT_Matrix_Multiply_Scaled( &top->font_matrix, &sub->font_matrix, scaling ); FT_Vector_Transform_Scaled( &sub->font_offset, &top->font_matrix, scaling ); sub->units_per_em = FT_MulDiv( sub->units_per_em, top->units_per_em, scaling ); } } else { sub->font_matrix = top->font_matrix; sub->font_offset = top->font_offset; sub->units_per_em = top->units_per_em; } matrix = &sub->font_matrix; offset = &sub->font_offset; upm = &sub->units_per_em; temp = FT_ABS( matrix->yy ); if ( temp != 0x10000L ) { *upm = FT_DivFix( *upm, temp ); matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp ); matrix->yy = FT_DivFix( matrix->yy, temp ); offset->x = FT_DivFix( offset->x, temp ); offset->y = FT_DivFix( offset->y, temp ); } offset->x >>= 16; offset->y >>= 16; } if ( pure_cff ) { char* style_name = NULL; /* set up num_faces */ cffface->num_faces = cff->num_faces; /* compute number of glyphs */ if ( dict->cid_registry != 0xFFFFU ) cffface->num_glyphs = cff->charset.max_cid + 1; else cffface->num_glyphs = cff->charstrings_index.count; /* set global bbox, as well as EM size */ cffface->bbox.xMin = dict->font_bbox.xMin >> 16; cffface->bbox.yMin = dict->font_bbox.yMin >> 16; /* no `U' suffix here to 0xFFFF! */ cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16; cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16; cffface->units_per_EM = (FT_UShort)( dict->units_per_em ); cffface->ascender = (FT_Short)( cffface->bbox.yMax ); cffface->descender = (FT_Short)( cffface->bbox.yMin ); cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); if ( cffface->height < cffface->ascender - cffface->descender ) cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); cffface->underline_position = (FT_Short)( dict->underline_position >> 16 ); cffface->underline_thickness = (FT_Short)( dict->underline_thickness >> 16 ); /* retrieve font family & style name */ cffface->family_name = cff_index_get_name( cff, face_index ); if ( cffface->family_name ) { char* full = cff_index_get_sid_string( cff, dict->full_name ); char* fullp = full; char* family = cffface->family_name; char* family_name = NULL; remove_subset_prefix( cffface->family_name ); if ( dict->family_name ) { family_name = cff_index_get_sid_string( cff, dict->family_name ); if ( family_name ) family = family_name; } /* We try to extract the style name from the full name. */ /* We need to ignore spaces and dashes during the search. */ if ( full && family ) { while ( *fullp ) { /* skip common characters at the start of both strings */ if ( *fullp == *family ) { family++; fullp++; continue; } /* ignore spaces and dashes in full name during comparison */ if ( *fullp == ' ' || *fullp == '-' ) { fullp++; continue; } /* ignore spaces and dashes in family name during comparison */ if ( *family == ' ' || *family == '-' ) { family++; continue; } if ( !*family && *fullp ) { /* The full name begins with the same characters as the */ /* family name, with spaces and dashes removed. In this */ /* case, the remaining string in `fullp' will be used as */ /* the style name. */ style_name = cff_strcpy( memory, fullp ); /* remove the style part from the family name (if present) */ remove_style( cffface->family_name, style_name ); } break; } } } else { char *cid_font_name = cff_index_get_sid_string( cff, dict->cid_font_name ); /* do we have a `/FontName' for a CID-keyed font? */ if ( cid_font_name ) cffface->family_name = cff_strcpy( memory, cid_font_name ); } if ( style_name ) cffface->style_name = style_name; else /* assume "Regular" style if we don't know better */ cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); /*******************************************************************/ /* */ /* Compute face flags. */ /* */ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ FT_FACE_FLAG_HINTER; /* has native hinter */ if ( sfnt_format ) flags |= FT_FACE_FLAG_SFNT; /* fixed width font? */ if ( dict->is_fixed_pitch ) flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ #if 0 /* kerning available? */ if ( face->kern_pairs ) flags |= FT_FACE_FLAG_KERNING; #endif cffface->face_flags = flags; /*******************************************************************/ /* */ /* Compute style flags. */ /* */ flags = 0; if ( dict->italic_angle ) flags |= FT_STYLE_FLAG_ITALIC; { char *weight = cff_index_get_sid_string( cff, dict->weight ); if ( weight ) if ( !ft_strcmp( weight, "Bold" ) || !ft_strcmp( weight, "Black" ) ) flags |= FT_STYLE_FLAG_BOLD; } /* double check */ if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || !ft_strncmp( cffface->style_name, "Black", 5 ) ) flags |= FT_STYLE_FLAG_BOLD; cffface->style_flags = flags; } #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ /* has unset this flag because of the 3.0 `post' table. */ if ( dict->cid_registry == 0xFFFFU ) cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; #endif if ( dict->cid_registry != 0xFFFFU && pure_cff ) cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; /*******************************************************************/ /* */ /* Compute char maps. */ /* */ /* Try to synthesize a Unicode charmap if there is none available */ /* already. If an OpenType font contains a Unicode "cmap", we */ /* will use it, whatever be in the CFF part of the file. */ { FT_CharMapRec cmaprec; FT_CharMap cmap; FT_UInt nn; CFF_Encoding encoding = &cff->encoding; for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) { cmap = cffface->charmaps[nn]; /* Windows Unicode? */ if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && cmap->encoding_id == TT_MS_ID_UNICODE_CS ) goto Skip_Unicode; /* Apple Unicode platform id? */ if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) goto Skip_Unicode; /* Apple Unicode */ } /* since CID-keyed fonts don't contain glyph names, we can't */ /* construct a cmap */ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) goto Exit; #ifdef FT_MAX_CHARMAP_CACHEABLE if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE ) { FT_ERROR(( "cff_face_init: no Unicode cmap is found, " "and too many subtables (%d) to add synthesized cmap\n", nn )); goto Exit; } #endif /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; cmaprec.platform_id = TT_PLATFORM_MICROSOFT; cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; cmaprec.encoding = FT_ENCODING_UNICODE; nn = (FT_UInt)cffface->num_charmaps; error = FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, &cmaprec, NULL ); if ( error && FT_Err_No_Unicode_Glyph_Name != error ) goto Exit; error = FT_Err_Ok; /* if no Unicode charmap was previously selected, select this one */ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) cffface->charmap = cffface->charmaps[nn]; Skip_Unicode: #ifdef FT_MAX_CHARMAP_CACHEABLE if ( nn > FT_MAX_CHARMAP_CACHEABLE ) { FT_ERROR(( "cff_face_init: Unicode cmap is found, " "but too many preceding subtables (%d) to access\n", nn - 1 )); goto Exit; } #endif if ( encoding->count > 0 ) { FT_CMap_Class clazz; cmaprec.face = cffface; cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ if ( encoding->offset == 0 ) { cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } else if ( encoding->offset == 1 ) { cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } else { cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); } } } Exit: return error; }
T1_Face_Init( FT_Stream stream, T1_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Service_PsCMaps psnames; PSAux_Service psaux; T1_Font type1 = &face->type1; PS_FontInfo info = &type1->font_info; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( face_index ); FT_UNUSED( stream ); face->root.num_faces = 1; FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); face->psnames = psnames; face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); psaux = (PSAux_Service)face->psaux; face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "pshinter" ); /* open the tokenizer; this will also check the font format */ error = T1_Open_Face( face ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ if ( face_index != 0 ) { FT_ERROR(( "T1_Face_Init: invalid face index\n" )); error = T1_Err_Invalid_Argument; goto Exit; } /* now load the font program into the face object */ /* initialize the face object fields */ /* set up root face fields */ { FT_Face root = (FT_Face)&face->root; root->num_glyphs = type1->num_glyphs; root->face_index = face_index; root->face_flags = FT_FACE_FLAG_SCALABLE | FT_FACE_FLAG_HORIZONTAL | FT_FACE_FLAG_GLYPH_NAMES | FT_FACE_FLAG_HINTER; if ( info->is_fixed_pitch ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( face->blend ) root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; /* XXX: TODO -- add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ /* have a `/FontName' dictionary entry! */ root->family_name = info->family_name; /* assume "Regular" style if we don't know better */ root->style_name = (char *)"Regular"; if ( root->family_name ) { char* full = info->full_name; char* family = root->family_name; if ( full ) { while ( *full ) { if ( *full == *family ) { family++; full++; } else { if ( *full == ' ' || *full == '-' ) full++; else if ( *family == ' ' || *family == '-' ) family++; else { if ( !*family ) root->style_name = full; break; } } } } } else { /* do we have a `/FontName'? */ if ( type1->font_name ) root->family_name = type1->font_name; } /* compute style flags */ root->style_flags = 0; if ( info->italic_angle ) root->style_flags |= FT_STYLE_FLAG_ITALIC; if ( info->weight ) { if ( !ft_strcmp( info->weight, "Bold" ) || !ft_strcmp( info->weight, "Black" ) ) root->style_flags |= FT_STYLE_FLAG_BOLD; } /* no embedded bitmap support */ root->num_fixed_sizes = 0; root->available_sizes = 0; root->bbox.xMin = type1->font_bbox.xMin >> 16; root->bbox.yMin = type1->font_bbox.yMin >> 16; root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFFU ) >> 16; root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFFU ) >> 16; /* Set units_per_EM if we didn't set it in parse_font_matrix. */ if ( !root->units_per_EM ) root->units_per_EM = 1000; root->ascender = (FT_Short)( root->bbox.yMax ); root->descender = (FT_Short)( root->bbox.yMin ); root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 ); if ( root->height < root->ascender - root->descender ) root->height = (FT_Short)( root->ascender - root->descender ); /* now compute the maximum advance width */ root->max_advance_width = (FT_Short)( root->bbox.xMax ); { FT_Pos max_advance; error = T1_Compute_Max_Advance( face, &max_advance ); /* in case of error, keep the standard width */ if ( !error ) root->max_advance_width = (FT_Short)max_advance; else error = 0; /* clear error */ } root->max_advance_height = root->height; root->underline_position = (FT_Short)info->underline_position; root->underline_thickness = (FT_Short)info->underline_thickness; } { FT_Face root = &face->root; if ( psnames && psaux ) { FT_CharMapRec charmap; T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; FT_CMap_Class clazz; charmap.face = root; /* first of all, try to synthetize a Unicode charmap */ charmap.platform_id = 3; charmap.encoding_id = 1; charmap.encoding = FT_ENCODING_UNICODE; FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); /* now, generate an Adobe Standard encoding when appropriate */ charmap.platform_id = 7; clazz = NULL; switch ( type1->encoding_type ) { case T1_ENCODING_TYPE_STANDARD: charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.encoding_id = TT_ADOBE_ID_STANDARD; clazz = cmap_classes->standard; break; case T1_ENCODING_TYPE_EXPERT: charmap.encoding = FT_ENCODING_ADOBE_EXPERT; charmap.encoding_id = TT_ADOBE_ID_EXPERT; clazz = cmap_classes->expert; break; case T1_ENCODING_TYPE_ARRAY: charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; charmap.encoding_id = TT_ADOBE_ID_CUSTOM; clazz = cmap_classes->custom; break; case T1_ENCODING_TYPE_ISOLATIN1: charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; charmap.encoding_id = TT_ADOBE_ID_LATIN_1; clazz = cmap_classes->unicode; break; default: ; } if ( clazz ) FT_CMap_New( clazz, NULL, &charmap, NULL ); #if 0 /* Select default charmap */ if (root->num_charmaps) root->charmap = root->charmaps[0]; #endif } } Exit: return error; }
cff_face_init( FT_Stream stream, CFF_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; SFNT_Service sfnt; PSNames_Service psnames; PSHinter_Service pshinter; FT_Bool pure_cff = 1; FT_Bool sfnt_format = 0; sfnt = (SFNT_Service)FT_Get_Module_Interface( face->root.driver->root.library, "sfnt" ); if ( !sfnt ) goto Bad_Format; psnames = (PSNames_Service)FT_Get_Module_Interface( face->root.driver->root.library, "psnames" ); pshinter = (PSHinter_Service)FT_Get_Module_Interface( face->root.driver->root.library, "pshinter" ); /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; /* check that we have a valid OpenType file */ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ { FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); goto Bad_Format; } /* if we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) return CFF_Err_Ok; sfnt_format = 1; /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ /* font in the later case; it doesn't have a `head' table */ error = face->goto_table( face, TTAG_head, stream, 0 ); if ( !error ) { pure_cff = 0; /* load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; } else { /* load the `cmap' table by hand */ error = sfnt->load_charmaps( face, stream ); if ( error ) goto Exit; /* XXX: we don't load the GPOS table, as OpenType Layout */ /* support will be added later to a layout library on top of */ /* FreeType 2 */ } /* now, load the CFF part of the file */ error = face->goto_table( face, TTAG_CFF, stream, 0 ); if ( error ) goto Exit; } else { /* rewind to start of file; we are going to load a pure-CFF font */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; error = CFF_Err_Ok; } /* now load and parse the CFF table in the file */ { CFF_Font cff; FT_Memory memory = face->root.memory; FT_Face root; FT_Int32 flags; if ( FT_NEW( cff ) ) goto Exit; face->extra.data = cff; error = cff_font_load( stream, face_index, cff ); if ( error ) goto Exit; cff->pshinter = pshinter; cff->psnames = psnames; /* Complement the root flags with some interesting information. */ /* Note that this is only necessary for pure CFF and CEF fonts. */ root = &face->root; root->num_glyphs = cff->num_glyphs; if ( pure_cff ) { CFF_FontRecDict dict = &cff->top_font.font_dict; /* we need the `PSNames' module for pure-CFF and CEF formats */ if ( !psnames ) { FT_ERROR(( "cff_face_init:" )); FT_ERROR(( " cannot open CFF & CEF fonts\n" )); FT_ERROR(( " " )); FT_ERROR(( " without the `PSNames' module\n" )); goto Bad_Format; } /* Set up num_faces. */ root->num_faces = cff->num_faces; /* compute number of glyphs */ if ( dict->cid_registry ) root->num_glyphs = dict->cid_count; else root->num_glyphs = cff->charstrings_index.count; /* set global bbox, as well as EM size */ root->bbox.xMin = dict->font_bbox.xMin >> 16; root->bbox.yMin = dict->font_bbox.yMin >> 16; root->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16; root->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16; root->ascender = (FT_Short)( root->bbox.yMax ); root->descender = (FT_Short)( root->bbox.yMin ); root->height = (FT_Short)( ( ( root->ascender - root->descender ) * 12 ) / 10 ); if ( dict->units_per_em ) root->units_per_EM = dict->units_per_em; else root->units_per_EM = 1000; /* retrieve font family & style name */ root->family_name = cff_index_get_name( &cff->name_index, face_index ); if ( dict->cid_registry ) root->style_name = cff_strcpy( memory, "Regular" ); /* XXXX */ else root->style_name = cff_index_get_sid_string( &cff->string_index, dict->weight, psnames ); /*******************************************************************/ /* */ /* Compute face flags. */ /* */ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ if ( sfnt_format ) flags |= FT_FACE_FLAG_SFNT; /* fixed width font? */ if ( dict->is_fixed_pitch ) flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ #if 0 /* kerning available? */ if ( face->kern_pairs ) flags |= FT_FACE_FLAG_KERNING; #endif #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES flags |= FT_FACE_FLAG_GLYPH_NAMES; #endif root->face_flags = flags; /*******************************************************************/ /* */ /* Compute style flags. */ /* */ flags = 0; if ( dict->italic_angle ) flags |= FT_STYLE_FLAG_ITALIC; /* XXX: may not be correct */ if ( cff->top_font.private_dict.force_bold ) flags |= FT_STYLE_FLAG_BOLD; root->style_flags = flags; } /*******************************************************************/ /* */ /* Compute char maps. */ /* */ /* Try to synthetize a Unicode charmap if there is none available */ /* already. If an OpenType font contains a Unicode "cmap", we */ /* will use it, whatever be in the CFF part of the file. */ { FT_CharMapRec cmaprec; FT_CharMap cmap; FT_UInt nn; CFF_Encoding encoding = &cff->encoding; for ( nn = 0; nn < (FT_UInt) root->num_charmaps; nn++ ) { cmap = root->charmaps[nn]; /* Windows Unicode (3,1)? */ if ( cmap->platform_id == 3 && cmap->encoding_id == 1 ) goto Skip_Unicode; /* Deprecated Unicode platform id? */ if ( cmap->platform_id == 0 ) goto Skip_Unicode; /* Standard Unicode (deprecated) */ } /* we didn't find a Unicode charmap, synthetize one */ cmaprec.face = root; cmaprec.platform_id = 3; cmaprec.encoding_id = 1; cmaprec.encoding = FT_ENCODING_UNICODE; nn = (FT_UInt) root->num_charmaps; FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL ); /* if no Unicode charmap was previously selected, select this one */ if ( root->charmap == NULL && nn != (FT_UInt) root->num_charmaps ) root->charmap = root->charmaps[nn]; Skip_Unicode: if ( encoding->count > 0 ) { FT_CMap_Class clazz; cmaprec.face = root; cmaprec.platform_id = 7; /* Adobe platform id */ if ( encoding->offset == 0 ) { cmaprec.encoding_id = 0; cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; clazz = &cff_cmap_encoding_class_rec; } else if ( encoding->offset == 1 ) { cmaprec.encoding_id = 1; cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; clazz = &cff_cmap_encoding_class_rec; } else { cmaprec.encoding_id = 3; cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; clazz = &cff_cmap_encoding_class_rec; } FT_CMap_New( clazz, NULL, &cmaprec, NULL ); } } } Exit: return error; Bad_Format: error = CFF_Err_Unknown_File_Format; goto Exit; }
T42_Face_Init( FT_Stream stream, T42_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params) { FT_Error error; PSNames_Service psnames; PSAux_Service psaux; FT_Face root = (FT_Face)&face->root; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( face_index ); FT_UNUSED( stream ); face->ttf_face = NULL; face->root.num_faces = 1; face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" ); psnames = (PSNames_Service)face->psnames; face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); psaux = (PSAux_Service)face->psaux; /* open the tokenizer, this will also check the font format */ error = T42_Open_Face( face ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ if ( face_index != 0 ) { FT_ERROR(( "T42_Face_Init: invalid face index\n" )); error = T42_Err_Invalid_Argument; goto Exit; } /* Now, load the font program into the face object */ /* Init the face object fields */ /* Now set up root face fields */ root->num_glyphs = face->type1.num_glyphs; root->num_charmaps = 0; root->face_index = face_index; root->face_flags = FT_FACE_FLAG_SCALABLE; root->face_flags |= FT_FACE_FLAG_HORIZONTAL; root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; if ( face->type1.font_info.is_fixed_pitch ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: TODO -- add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ /* have a `/FontName' dictionary entry! */ root->family_name = face->type1.font_info.family_name; if ( root->family_name ) { char* full = face->type1.font_info.full_name; char* family = root->family_name; if ( full ) { while ( *family && *full == *family ) { family++; full++; } root->style_name = ( *full == ' ' ? full + 1 : (char *)"Regular" ); } else root->style_name = (char *)"Regular"; } else { /* do we have a `/FontName'? */ if ( face->type1.font_name ) { root->family_name = face->type1.font_name; root->style_name = (char *)"Regular"; } } /* no embedded bitmap support */ root->num_fixed_sizes = 0; root->available_sizes = 0; /* Load the TTF font embedded in the T42 font */ error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ), face->ttf_data, face->ttf_size, 0, &face->ttf_face ); if ( error ) goto Exit; FT_Done_Size( face->ttf_face->size ); /* Ignore info in FontInfo dictionary and use the info from the */ /* loaded TTF font. The PostScript interpreter also ignores it. */ root->bbox = face->ttf_face->bbox; root->units_per_EM = face->ttf_face->units_per_EM; root->ascender = face->ttf_face->ascender; root->descender = face->ttf_face->descender; root->height = face->ttf_face->height; root->max_advance_width = face->ttf_face->max_advance_width; root->max_advance_height = face->ttf_face->max_advance_height; root->underline_position = face->type1.font_info.underline_position; root->underline_thickness = face->type1.font_info.underline_thickness; root->internal->max_points = 0; root->internal->max_contours = 0; /* compute style flags */ root->style_flags = 0; if ( face->type1.font_info.italic_angle ) root->style_flags |= FT_STYLE_FLAG_ITALIC; if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) root->style_flags |= FT_STYLE_FLAG_BOLD; if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) root->face_flags |= FT_FACE_FLAG_VERTICAL; #ifdef FT_CONFIG_OPTION_USE_CMAPS { if ( psnames && psaux ) { FT_CharMapRec charmap; T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; FT_CMap_Class clazz; charmap.face = root; /* first of all, try to synthetize a Unicode charmap */ charmap.platform_id = 3; charmap.encoding_id = 1; charmap.encoding = ft_encoding_unicode; FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); /* now, generate an Adobe Standard encoding when appropriate */ charmap.platform_id = 7; clazz = NULL; switch ( face->type1.encoding_type ) { case T1_ENCODING_TYPE_STANDARD: charmap.encoding = ft_encoding_adobe_standard; charmap.encoding_id = 0; clazz = cmap_classes->standard; break; case T1_ENCODING_TYPE_EXPERT: charmap.encoding = ft_encoding_adobe_expert; charmap.encoding_id = 1; clazz = cmap_classes->expert; break; case T1_ENCODING_TYPE_ARRAY: charmap.encoding = ft_encoding_adobe_custom; charmap.encoding_id = 2; clazz = cmap_classes->custom; break; case T1_ENCODING_TYPE_ISOLATIN1: charmap.encoding = ft_encoding_latin_1; charmap.encoding_id = 3; clazz = cmap_classes->unicode; break; default: ; } if ( clazz ) FT_CMap_New( clazz, NULL, &charmap, NULL ); /* Select default charmap */ if (root->num_charmaps) root->charmap = root->charmaps[0]; } } #else /* !FT_CONFIG_OPTION_USE_CMAPS */ /* charmap support -- synthetize unicode charmap if possible */ { FT_CharMap charmap = face->charmaprecs; /* synthesize a Unicode charmap if there is support in the `PSNames' */ /* module */ if ( psnames && psnames->unicode_value ) { error = psnames->build_unicodes( root->memory, face->type1.num_glyphs, (const char**)face->type1.glyph_names, &face->unicode_map ); if ( !error ) { root->charmap = charmap; charmap->face = (FT_Face)face; charmap->encoding = ft_encoding_unicode; charmap->platform_id = 3; charmap->encoding_id = 1; charmap++; } /* XXX: Is the following code correct? It is used in t1objs.c */ /* simply clear the error in case of failure (which really) */ /* means that out of memory or no unicode glyph names */ error = T42_Err_Ok; } /* now, support either the standard, expert, or custom encoding */ charmap->face = (FT_Face)face; charmap->platform_id = 7; /* a new platform id for Adobe fonts? */ switch ( face->type1.encoding_type ) { case T1_ENCODING_TYPE_STANDARD: charmap->encoding = ft_encoding_adobe_standard; charmap->encoding_id = 0; break; case T1_ENCODING_TYPE_EXPERT: charmap->encoding = ft_encoding_adobe_expert; charmap->encoding_id = 1; break; case T1_ENCODING_TYPE_ARRAY: charmap->encoding = ft_encoding_adobe_custom; charmap->encoding_id = 2; break; case T1_ENCODING_TYPE_ISOLATIN1: charmap->encoding = ft_encoding_latin_1; charmap->encoding_id = 3; break; default: FT_ERROR(( "T42_Face_Init: invalid encoding\n" )); error = T42_Err_Invalid_File_Format; goto Exit; } root->charmaps = face->charmaps; root->num_charmaps = charmap - face->charmaprecs + 1; face->charmaps[0] = &face->charmaprecs[0]; face->charmaps[1] = &face->charmaprecs[1]; } #endif /* !FT_CONFIG_OPTION_USE_CMAPS */ Exit: return error; }
cid_face_init( FT_Stream stream, FT_Face cidface, /* CID_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { CID_Face face = (CID_Face)cidface; FT_Error error; PSAux_Service psaux; PSHinter_Service pshinter; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( stream ); cidface->num_faces = 1; psaux = (PSAux_Service)face->psaux; if ( !psaux ) { psaux = (PSAux_Service)FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); face->psaux = psaux; } pshinter = (PSHinter_Service)face->pshinter; if ( !pshinter ) { pshinter = (PSHinter_Service)FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "pshinter" ); face->pshinter = pshinter; } /* open the tokenizer; this will also check the font format */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; error = cid_face_open( face, face_index ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ /* XXX: handle CID fonts with more than a single face */ if ( face_index != 0 ) { FT_ERROR(( "cid_face_init: invalid face index\n" )); error = CID_Err_Invalid_Argument; goto Exit; } /* now load the font program into the face object */ /* initialize the face object fields */ /* set up root face fields */ { CID_FaceInfo cid = &face->cid; PS_FontInfo info = &cid->font_info; cidface->num_glyphs = cid->cid_count; cidface->num_charmaps = 0; cidface->face_index = face_index; cidface->face_flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ FT_FACE_FLAG_HINTER; /* has native hinter */ if ( info->is_fixed_pitch ) cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: TODO: add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ /* have a /FontName dictionary entry! */ cidface->family_name = info->family_name; /* assume "Regular" style if we don't know better */ cidface->style_name = (char *)"Regular"; if ( cidface->family_name ) { char* full = info->full_name; char* family = cidface->family_name; if ( full ) { while ( *full ) { if ( *full == *family ) { family++; full++; } else { if ( *full == ' ' || *full == '-' ) full++; else if ( *family == ' ' || *family == '-' ) family++; else { if ( !*family ) cidface->style_name = full; break; } } } } } else { /* do we have a `/FontName'? */ if ( cid->cid_font_name ) cidface->family_name = cid->cid_font_name; } /* compute style flags */ cidface->style_flags = 0; if ( info->italic_angle ) cidface->style_flags |= FT_STYLE_FLAG_ITALIC; if ( info->weight ) { if ( !ft_strcmp( info->weight, "Bold" ) || !ft_strcmp( info->weight, "Black" ) ) cidface->style_flags |= FT_STYLE_FLAG_BOLD; } /* no embedded bitmap support */ cidface->num_fixed_sizes = 0; cidface->available_sizes = 0; cidface->bbox.xMin = cid->font_bbox.xMin >> 16; cidface->bbox.yMin = cid->font_bbox.yMin >> 16; /* no `U' suffix here to 0xFFFF! */ cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFF ) >> 16; cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFF ) >> 16; if ( !cidface->units_per_EM ) cidface->units_per_EM = 1000; cidface->ascender = (FT_Short)( cidface->bbox.yMax ); cidface->descender = (FT_Short)( cidface->bbox.yMin ); cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 ); if ( cidface->height < cidface->ascender - cidface->descender ) cidface->height = (FT_Short)( cidface->ascender - cidface->descender ); cidface->underline_position = (FT_Short)info->underline_position; cidface->underline_thickness = (FT_Short)info->underline_thickness; } Exit: return error; }
T42_Face_Init( FT_Stream stream, T42_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Service_PsCMaps psnames; PSAux_Service psaux; FT_Face root = (FT_Face)&face->root; T1_Font type1 = &face->type1; PS_FontInfo info = &type1->font_info; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( face_index ); FT_UNUSED( stream ); face->ttf_face = NULL; face->root.num_faces = 1; FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); face->psnames = psnames; face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); psaux = (PSAux_Service)face->psaux; /* open the tokenizer, this will also check the font format */ error = T42_Open_Face( face ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ if ( face_index != 0 ) { FT_ERROR(( "T42_Face_Init: invalid face index\n" )); error = T42_Err_Invalid_Argument; goto Exit; } /* Now load the font program into the face object */ /* Init the face object fields */ /* Now set up root face fields */ root->num_glyphs = type1->num_glyphs; root->num_charmaps = 0; root->face_index = face_index; root->face_flags = FT_FACE_FLAG_SCALABLE; root->face_flags |= FT_FACE_FLAG_HORIZONTAL; root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; if ( info->is_fixed_pitch ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: TODO -- add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ /* have a `/FontName' dictionary entry! */ root->family_name = info->family_name; /* assume "Regular" style if we don't know better */ root->style_name = (char *)"Regular"; if ( root->family_name ) { char* full = info->full_name; char* family = root->family_name; if ( full ) { while ( *full ) { if ( *full == *family ) { family++; full++; } else { if ( *full == ' ' || *full == '-' ) full++; else if ( *family == ' ' || *family == '-' ) family++; else { if ( !*family ) root->style_name = full; break; } } } } } else { /* do we have a `/FontName'? */ if ( type1->font_name ) root->family_name = type1->font_name; } /* no embedded bitmap support */ root->num_fixed_sizes = 0; root->available_sizes = 0; /* Load the TTF font embedded in the T42 font */ error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ), face->ttf_data, face->ttf_size, 0, &face->ttf_face ); if ( error ) goto Exit; FT_Done_Size( face->ttf_face->size ); /* Ignore info in FontInfo dictionary and use the info from the */ /* loaded TTF font. The PostScript interpreter also ignores it. */ root->bbox = face->ttf_face->bbox; root->units_per_EM = face->ttf_face->units_per_EM; root->ascender = face->ttf_face->ascender; root->descender = face->ttf_face->descender; root->height = face->ttf_face->height; root->max_advance_width = face->ttf_face->max_advance_width; root->max_advance_height = face->ttf_face->max_advance_height; root->underline_position = (FT_Short)info->underline_position; root->underline_thickness = (FT_Short)info->underline_thickness; root->internal->max_points = 0; root->internal->max_contours = 0; /* compute style flags */ root->style_flags = 0; if ( info->italic_angle ) root->style_flags |= FT_STYLE_FLAG_ITALIC; if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) root->style_flags |= FT_STYLE_FLAG_BOLD; if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) root->face_flags |= FT_FACE_FLAG_VERTICAL; { if ( psnames && psaux ) { FT_CharMapRec charmap; T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; FT_CMap_Class clazz; charmap.face = root; /* first of all, try to synthetize a Unicode charmap */ charmap.platform_id = 3; charmap.encoding_id = 1; charmap.encoding = FT_ENCODING_UNICODE; FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); /* now, generate an Adobe Standard encoding when appropriate */ charmap.platform_id = 7; clazz = NULL; switch ( type1->encoding_type ) { case T1_ENCODING_TYPE_STANDARD: charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.encoding_id = 0; clazz = cmap_classes->standard; break; case T1_ENCODING_TYPE_EXPERT: charmap.encoding = FT_ENCODING_ADOBE_EXPERT; charmap.encoding_id = 1; clazz = cmap_classes->expert; break; case T1_ENCODING_TYPE_ARRAY: charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; charmap.encoding_id = 2; clazz = cmap_classes->custom; break; case T1_ENCODING_TYPE_ISOLATIN1: charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; charmap.encoding_id = 3; clazz = cmap_classes->unicode; break; default: ; } if ( clazz ) FT_CMap_New( clazz, NULL, &charmap, NULL ); #if 0 /* Select default charmap */ if ( root->num_charmaps ) root->charmap = root->charmaps[0]; #endif } } Exit: return error; }
cid_face_init( FT_Stream stream, CID_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; PSNames_Service psnames; PSAux_Service psaux; PSHinter_Service pshinter; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( face_index ); FT_UNUSED( stream ); face->root.num_faces = 1; psnames = (PSNames_Service)face->psnames; if ( !psnames ) { psnames = (PSNames_Service)FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" ); face->psnames = psnames; } psaux = (PSAux_Service)face->psaux; if ( !psaux ) { psaux = (PSAux_Service)FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); face->psaux = psaux; } pshinter = (PSHinter_Service)face->pshinter; if ( !pshinter ) { pshinter = (PSHinter_Service)FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "pshinter" ); face->pshinter = pshinter; } /* open the tokenizer; this will also check the font format */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; error = cid_face_open( face ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ if ( face_index != 0 ) { FT_ERROR(( "cid_face_init: invalid face index\n" )); error = CID_Err_Invalid_Argument; goto Exit; } /* Now, load the font program into the face object */ { /* Init the face object fields */ /* Now set up root face fields */ { FT_Face root = (FT_Face)&face->root; root->num_glyphs = face->cid.cid_count; root->num_charmaps = 0; root->face_index = face_index; root->face_flags = FT_FACE_FLAG_SCALABLE; root->face_flags |= FT_FACE_FLAG_HORIZONTAL; if ( face->cid.font_info.is_fixed_pitch ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: TODO: add kerning with .afm support */ /* get style name -- be careful, some broken fonts only */ /* have a /FontName dictionary entry! */ root->family_name = face->cid.font_info.family_name; if ( root->family_name ) { char* full = face->cid.font_info.full_name; char* family = root->family_name; while ( *family && *full == *family ) { family++; full++; } root->style_name = ( *full == ' ' ) ? full + 1 : (char *)"Regular"; } else { /* do we have a `/FontName'? */ if ( face->cid.cid_font_name ) { root->family_name = face->cid.cid_font_name; root->style_name = (char *)"Regular"; } } /* no embedded bitmap support */ root->num_fixed_sizes = 0; root->available_sizes = 0; root->bbox.xMin = face->cid.font_bbox.xMin >> 16; root->bbox.yMin = face->cid.font_bbox.yMin >> 16; root->bbox.xMax = ( face->cid.font_bbox.xMax + 0xFFFFU ) >> 16; root->bbox.yMax = ( face->cid.font_bbox.yMax + 0xFFFFU ) >> 16; if ( !root->units_per_EM ) root->units_per_EM = 1000; root->ascender = (FT_Short)( root->bbox.yMax ); root->descender = (FT_Short)( root->bbox.yMin ); root->height = (FT_Short)( ( ( root->ascender + root->descender ) * 12 ) / 10 ); root->underline_position = face->cid.font_info.underline_position; root->underline_thickness = face->cid.font_info.underline_thickness; root->internal->max_points = 0; root->internal->max_contours = 0; } } Exit: return error; }
tt_face_init( FT_Stream stream, FT_Face ttface, /* TT_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Library library; SFNT_Service sfnt; TT_Face face = (TT_Face)ttface; FT_TRACE2(( "TTF driver\n" )); library = ttface->driver->root.library; sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) { FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; } /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; /* check that we have a valid TrueType file */ FT_TRACE2(( " " )); error = sfnt->init_face( stream, face, face_index, num_params, params ); /* Stream may have changed. */ stream = face->root.stream; if ( error ) goto Exit; /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ /* The 0x00020000 tag is completely undocumented; some fonts from */ /* Arphic made for Chinese Windows 3.1 have this. */ if ( face->format_tag != 0x00010000L && /* MS fonts */ face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ face->format_tag != TTAG_true ) /* Mac fonts */ { FT_TRACE2(( " not a TTF font\n" )); goto Bad_Format; } #ifdef TT_USE_BYTECODE_INTERPRETER ttface->face_flags |= FT_FACE_FLAG_HINTER; #endif /* If we are performing a simple font format check, exit immediately. */ if ( face_index < 0 ) return FT_Err_Ok; /* Load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; if ( tt_check_trickyness( ttface ) ) ttface->face_flags |= FT_FACE_FLAG_TRICKY; error = tt_face_load_hdmx( face, stream ); if ( error ) goto Exit; if ( FT_IS_SCALABLE( ttface ) ) { #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( !ttface->internal->incremental_interface ) #endif { error = tt_face_load_loca( face, stream ); /* having a (non-zero) `glyf' table without */ /* a `loca' table is not valid */ if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) ) goto Exit; if ( error ) goto Exit; } /* `fpgm', `cvt', and `prep' are optional */ error = tt_face_load_cvt( face, stream ); if ( error && FT_ERR_NEQ( error, Table_Missing ) ) goto Exit; error = tt_face_load_fpgm( face, stream ); if ( error && FT_ERR_NEQ( error, Table_Missing ) ) goto Exit; error = tt_face_load_prep( face, stream ); if ( error && FT_ERR_NEQ( error, Table_Missing ) ) goto Exit; /* Check the scalable flag based on `loca'. */ #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( !ttface->internal->incremental_interface ) #endif { if ( ttface->num_fixed_sizes && face->glyph_locations && tt_check_single_notdef( ttface ) ) { FT_TRACE5(( "tt_face_init:" " Only the `.notdef' glyph has an outline.\n" " " " Resetting scalable flag to FALSE.\n" )); ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; } } } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { FT_Int instance_index = face_index >> 16; if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && instance_index > 0 ) { error = TT_Get_MM_Var( face, NULL ); if ( error ) goto Exit; if ( face->blend->mmvar->namedstyle ) { FT_Memory memory = ttface->memory; FT_Var_Named_Style* named_style; FT_String* style_name; /* in `face_index', the instance index starts with value 1 */ named_style = face->blend->mmvar->namedstyle + instance_index - 1; error = sfnt->get_name( face, (FT_UShort)named_style->strid, &style_name ); if ( error ) goto Exit; /* set style name; if already set, replace it */ if ( face->root.style_name ) FT_FREE( face->root.style_name ); face->root.style_name = style_name; /* finally, select the named instance */ error = TT_Set_Var_Design( face, face->blend->mmvar->num_axis, named_style->coords ); if ( error ) goto Exit; } } } #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ /* initialize standard glyph loading routines */ TT_Init_Glyph_Loading( face ); Exit: return error; Bad_Format: error = FT_THROW( Unknown_File_Format ); goto Exit; }
T1_Face_Init( FT_Stream stream, FT_Face t1face, /* T1_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { T1_Face face = (T1_Face)t1face; FT_Error error; FT_Service_PsCMaps psnames; PSAux_Service psaux; T1_Font type1 = &face->type1; PS_FontInfo info = &type1->font_info; FT_UNUSED( num_params ); FT_UNUSED( params ); FT_UNUSED( stream ); face->root.num_faces = 1; FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); face->psnames = psnames; face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" ); psaux = (PSAux_Service)face->psaux; if ( !psaux ) { FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; } face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "pshinter" ); FT_TRACE2(( "Type 1 driver\n" )); /* open the tokenizer; this will also check the font format */ error = T1_Open_Face( face ); if ( error ) goto Exit; /* if we just wanted to check the format, leave successfully now */ if ( face_index < 0 ) goto Exit; /* check the face index */ if ( ( face_index & 0xFFFF ) > 0 ) { FT_ERROR(( "T1_Face_Init: invalid face index\n" )); error = FT_THROW( Invalid_Argument ); goto Exit; } /* now load the font program into the face object */ /* initialize the face object fields */ /* set up root face fields */ { FT_Face root = (FT_Face)&face->root; root->num_glyphs = type1->num_glyphs; root->face_index = 0; root->face_flags |= FT_FACE_FLAG_SCALABLE | FT_FACE_FLAG_HORIZONTAL | FT_FACE_FLAG_GLYPH_NAMES | FT_FACE_FLAG_HINTER; if ( info->is_fixed_pitch ) root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( face->blend ) root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; /* The following code to extract the family and the style is very */ /* simplistic and might get some things wrong. For a full-featured */ /* algorithm you might have a look at the whitepaper given at */ /* */ /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ /* get style name -- be careful, some broken fonts only */ /* have a `/FontName' dictionary entry! */ root->family_name = info->family_name; root->style_name = NULL; if ( root->family_name ) { char* full = info->full_name; char* family = root->family_name; if ( full ) { FT_Bool the_same = TRUE; while ( *full ) { if ( *full == *family ) { family++; full++; } else { if ( *full == ' ' || *full == '-' ) full++; else if ( *family == ' ' || *family == '-' ) family++; else { the_same = FALSE; if ( !*family ) root->style_name = full; break; } } } if ( the_same ) root->style_name = (char *)"Regular"; } } else { /* do we have a `/FontName'? */ if ( type1->font_name ) root->family_name = type1->font_name; } if ( !root->style_name ) { if ( info->weight ) root->style_name = info->weight; else /* assume `Regular' style because we don't know better */ root->style_name = (char *)"Regular"; } /* compute style flags */ root->style_flags = 0; if ( info->italic_angle ) root->style_flags |= FT_STYLE_FLAG_ITALIC; if ( info->weight ) { if ( !ft_strcmp( info->weight, "Bold" ) || !ft_strcmp( info->weight, "Black" ) ) root->style_flags |= FT_STYLE_FLAG_BOLD; } /* no embedded bitmap support */ root->num_fixed_sizes = 0; root->available_sizes = NULL; root->bbox.xMin = type1->font_bbox.xMin >> 16; root->bbox.yMin = type1->font_bbox.yMin >> 16; /* no `U' suffix here to 0xFFFF! */ root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16; root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16; /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */ if ( !root->units_per_EM ) root->units_per_EM = 1000; root->ascender = (FT_Short)( root->bbox.yMax ); root->descender = (FT_Short)( root->bbox.yMin ); root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 ); if ( root->height < root->ascender - root->descender ) root->height = (FT_Short)( root->ascender - root->descender ); /* now compute the maximum advance width */ root->max_advance_width = (FT_Short)( root->bbox.xMax ); { FT_Pos max_advance; error = T1_Compute_Max_Advance( face, &max_advance ); /* in case of error, keep the standard width */ if ( !error ) root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance ); else error = FT_Err_Ok; /* clear error */ } root->max_advance_height = root->height; root->underline_position = (FT_Short)info->underline_position; root->underline_thickness = (FT_Short)info->underline_thickness; } { FT_Face root = &face->root; if ( psnames ) { FT_CharMapRec charmap; T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; FT_CMap_Class clazz; charmap.face = root; /* first of all, try to synthesize a Unicode charmap */ charmap.platform_id = TT_PLATFORM_MICROSOFT; charmap.encoding_id = TT_MS_ID_UNICODE_CS; charmap.encoding = FT_ENCODING_UNICODE; error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); if ( error && FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) goto Exit; error = FT_Err_Ok; /* now, generate an Adobe Standard encoding when appropriate */ charmap.platform_id = TT_PLATFORM_ADOBE; clazz = NULL; switch ( type1->encoding_type ) { case T1_ENCODING_TYPE_STANDARD: charmap.encoding = FT_ENCODING_ADOBE_STANDARD; charmap.encoding_id = TT_ADOBE_ID_STANDARD; clazz = cmap_classes->standard; break; case T1_ENCODING_TYPE_EXPERT: charmap.encoding = FT_ENCODING_ADOBE_EXPERT; charmap.encoding_id = TT_ADOBE_ID_EXPERT; clazz = cmap_classes->expert; break; case T1_ENCODING_TYPE_ARRAY: charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; charmap.encoding_id = TT_ADOBE_ID_CUSTOM; clazz = cmap_classes->custom; break; case T1_ENCODING_TYPE_ISOLATIN1: charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; charmap.encoding_id = TT_ADOBE_ID_LATIN_1; clazz = cmap_classes->unicode; break; default: ; } if ( clazz ) error = FT_CMap_New( clazz, NULL, &charmap, NULL ); #if 0 /* Select default charmap */ if (root->num_charmaps) root->charmap = root->charmaps[0]; #endif } } Exit: return error; }
sfnt_init_face( FT_Stream stream, TT_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Library library = face->root.driver->root.library; SFNT_Service sfnt; /* for now, parameters are unused */ FT_UNUSED( num_params ); FT_UNUSED( params ); sfnt = (SFNT_Service)face->sfnt; if ( !sfnt ) { sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) { FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); return FT_THROW( Missing_Module ); } face->sfnt = sfnt; face->goto_table = sfnt->goto_table; } FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); FT_TRACE2(( "SFNT driver\n" )); error = sfnt_open_font( stream, face ); if ( error ) return error; /* Stream may have changed in sfnt_open_font. */ stream = face->root.stream; FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); if ( face_index < 0 ) face_index = 0; if ( face_index >= face->ttc_header.count ) return FT_THROW( Invalid_Argument ); if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) return error; /* check that we have a valid TrueType file */ error = sfnt->load_font_dir( face, stream ); if ( error ) return error; face->root.num_faces = face->ttc_header.count; face->root.face_index = face_index; return error; }
tt_face_init( FT_Stream stream, FT_Face ttface, /* TT_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Library library; SFNT_Service sfnt; TT_Face face = (TT_Face)ttface; library = face->root.driver->root.library; sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) goto Bad_Format; /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; /* check that we have a valid TrueType file */ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ /* The 0x00020000 tag is completely undocumented; some fonts from */ /* Arphic made for Chinese Windows 3.1 have this. */ if ( face->format_tag != 0x00010000L && /* MS fonts */ face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ face->format_tag != TTAG_true ) /* Mac fonts */ { FT_TRACE2(( "[not a valid TTF font]\n" )); goto Bad_Format; } /* If we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) return TT_Err_Ok; /* Load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE ) { #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( !face->root.internal->incremental_interface ) error = tt_face_load_loca( face, stream ); if ( !error ) { error = tt_face_load_cvt( face, stream ); if ( !error ) error = tt_face_load_fpgm( face, stream ); } #else if ( !error ) error = tt_face_load_loca( face, stream ) || tt_face_load_cvt( face, stream ) || tt_face_load_fpgm( face, stream ); #endif } #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING /* Determine whether unpatented hinting is to be used for this face. */ face->unpatented_hinting = FT_BOOL ( library->debug_hooks[ FT_DEBUG_HOOK_UNPATENTED_HINTING ] != NULL ); { int i; for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) face->unpatented_hinting = TRUE; } #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ /* initialize standard glyph loading routines */ TT_Init_Glyph_Loading( face ); Exit: return error; Bad_Format: error = TT_Err_Unknown_File_Format; goto Exit; }
LOCAL_FUNC FT_Error SFNT_Init_Face(FT_Stream stream, TT_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter *params) { FT_Error error; FT_Library library = face->root.driver->root.library; SFNT_Interface *sfnt; SFNT_Header sfnt_header; /* for now, parameters are unused */ FT_UNUSED(num_params); FT_UNUSED(params); sfnt = (SFNT_Interface *)face->sfnt; if(!sfnt) { sfnt = (SFNT_Interface *)FT_Get_Module_Interface(library, "sfnt"); if(!sfnt) { error = FT_Err_Invalid_File_Format; goto Exit; } face->sfnt = sfnt; face->goto_table = sfnt->goto_table; } if(!face->psnames) { face->psnames = (PSNames_Interface *) FT_Get_Module_Interface(library, "psnames"); } /* check that we have a valid TrueType file */ error = sfnt->load_sfnt_header(face, stream, face_index, &sfnt_header); if(error) { goto Exit; } face->format_tag = sfnt_header.format_tag; face->num_tables = sfnt_header.num_tables; /* Load font directory */ error = sfnt->load_directory(face, stream, &sfnt_header); if(error) { goto Exit; } face->root.num_faces = face->ttc_header.count; if(face->root.num_faces < 1) { face->root.num_faces = 1; } Exit: return error; }