af_face_globals_is_digit( AF_FaceGlobals globals, FT_UInt gindex ) { if ( gindex < (FT_ULong)globals->glyph_count ) return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT ); return FT_BOOL( 0 ); }
ftc_snode_compare( FTC_Node ftcsnode, FT_Pointer ftcgquery, FTC_Cache cache ) { FTC_SNode snode = (FTC_SNode)ftcsnode; FTC_GQuery gquery = (FTC_GQuery)ftcgquery; FTC_GNode gnode = FTC_GNODE( snode ); FT_UInt gindex = gquery->gindex; FT_Bool result; result = FT_BOOL( gnode->family == gquery->family && (FT_UInt)( gindex - gnode->gindex ) < snode->count ); if ( result ) { /* check if we need to load the glyph bitmap now */ FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex ); if ( sbit->buffer == NULL && sbit->width != 255 ) { FT_ULong size; if ( !ftc_snode_load( snode, cache->manager, gindex, &size ) ) { cache->manager->cur_weight += size; } } } return result; }
static FT_Bool gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage, FT_UShort* format, GXV_Validator gxvalid ) { /* classic Microsoft-dialect */ #ifdef GXV_LOAD_TRACE_VARS FT_Bool horizontal; FT_Bool minimum; FT_Bool cross_stream; FT_Bool override; #endif FT_UNUSED( gxvalid ); /* reserved bits = 0 */ if ( coverage & 0xFDF0 ) return FALSE; #ifdef GXV_LOAD_TRACE_VARS horizontal = FT_BOOL( coverage & 1 ); minimum = FT_BOOL( ( coverage >> 1 ) & 1 ); cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 ); override = FT_BOOL( ( coverage >> 3 ) & 1 );
ftc_cmap_node_compare( FTC_CMapNode cnode, FTC_CMapQuery cquery ) { FT_UInt32 offset = (FT_UInt32)( cquery->char_code - cnode->first ); return FT_BOOL( offset < FTC_CMAP_INDICES_MAX ); }
ftc_glyph_node_compare( FTC_GlyphNode gnode, FTC_GlyphQuery gquery ) { FT_UInt start = (FT_UInt)gnode->item_start; FT_UInt count = (FT_UInt)gnode->item_count; return FT_BOOL( (FT_UInt)( gquery->gindex - start ) < count ); }
static FT_Bool ft_cubic_is_small_enough( FT_Vector* base, FT_Angle *angle_in, FT_Angle *angle_mid, FT_Angle *angle_out ) { FT_Vector d1, d2, d3; FT_Angle theta1, theta2; FT_Int close1, close2, close3; d1.x = base[2].x - base[3].x; d1.y = base[2].y - base[3].y; d2.x = base[1].x - base[2].x; d2.y = base[1].y - base[2].y; d3.x = base[0].x - base[1].x; d3.y = base[0].y - base[1].y; close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y ); if ( close1 || close3 ) { if ( close2 ) { /* basically a point */ *angle_in = *angle_out = *angle_mid = 0; } else if ( close1 ) { *angle_in = *angle_mid = FT_Atan2( d2.x, d2.y ); *angle_out = FT_Atan2( d3.x, d3.y ); } else /* close2 */ { *angle_in = FT_Atan2( d1.x, d1.y ); *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y ); } } else if ( close2 ) { *angle_in = *angle_mid = FT_Atan2( d1.x, d1.y ); *angle_out = FT_Atan2( d3.x, d3.y ); } else { *angle_in = FT_Atan2( d1.x, d1.y ); *angle_mid = FT_Atan2( d2.x, d2.y ); *angle_out = FT_Atan2( d3.x, d3.y ); } theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) ); theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) ); return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD && theta2 < FT_SMALL_CUBIC_THRESHOLD ); }
ftc_face_node_compare( FTC_MruNode ftcnode, FT_Pointer ftcface_id ) { FTC_FaceNode node = (FTC_FaceNode)ftcnode; FTC_FaceID face_id = (FTC_FaceID)ftcface_id; return FT_BOOL( node->face_id == face_id ); }
ftc_size_node_compare( FTC_SizeNode node, FTC_SizeQuery query ) { FT_Size size = node->size; return FT_BOOL( size->face == query->face && (FT_UInt)size->metrics.x_ppem == query->width && (FT_UInt)size->metrics.y_ppem == query->height ); }
ftc_cmap_node_remove_faceid( FTC_Node ftcnode, FT_Pointer ftcface_id, FTC_Cache cache ) { FTC_CMapNode node = (FTC_CMapNode)ftcnode; FTC_FaceID face_id = (FTC_FaceID)ftcface_id; FT_UNUSED( cache ); return FT_BOOL( node->face_id == face_id ); }
/* helper function used by ftc_face_node_done */ static FT_Bool ftc_size_node_compare_faceid( FTC_MruNode ftcnode, FT_Pointer ftcface_id ) { FTC_SizeNode node = (FTC_SizeNode)ftcnode; FTC_FaceID face_id = (FTC_FaceID)ftcface_id; return FT_BOOL( node->scaler.face_id == face_id ); }
ftc_gnode_compare( FTC_Node ftcgnode, FT_Pointer ftcgquery, FTC_Cache cache ) { FTC_GNode gnode = (FTC_GNode)ftcgnode; FTC_GQuery gquery = (FTC_GQuery)ftcgquery; FT_UNUSED( cache ); return FT_BOOL( gnode->family == gquery->family && gnode->gindex == gquery->gindex ); }
ftc_image_family_compare( FTC_ImageFamily ifam, FTC_ImageQuery iquery ) { FT_Bool result; result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) ); if ( result ) FTC_GLYPH_FAMILY_FOUND( ifam, iquery ); return result; }
ftc_cmap_node_remove_faceid( FTC_Node ftcnode, FT_Pointer ftcface_id, FTC_Cache cache, FT_Bool* list_changed ) { FTC_CMapNode node = (FTC_CMapNode)ftcnode; FTC_FaceID face_id = (FTC_FaceID)ftcface_id; FT_UNUSED( cache ); if ( list_changed ) *list_changed = FALSE; return FT_BOOL( node->face_id == face_id ); }
ftc_gnode_compare( FTC_Node ftcgnode, FT_Pointer ftcgquery, FTC_Cache cache, FT_Bool* list_changed ) { FTC_GNode gnode = (FTC_GNode)ftcgnode; FTC_GQuery gquery = (FTC_GQuery)ftcgquery; FT_UNUSED( cache ); if ( list_changed ) *list_changed = FALSE; return FT_BOOL( gnode->family == gquery->family && gnode->gindex == gquery->gindex ); }
ftc_cmap_node_compare( FTC_Node ftcnode, FT_Pointer ftcquery, FTC_Cache cache ) { FTC_CMapNode node = (FTC_CMapNode)ftcnode; FTC_CMapQuery query = (FTC_CMapQuery)ftcquery; FT_UNUSED( cache ); if ( node->face_id == query->face_id && node->cmap_index == query->cmap_index ) { FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first ); return FT_BOOL( offset < FTC_CMAP_INDICES_MAX ); } return 0; }
ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode, FT_Pointer ftcface_id, FTC_Cache cache ) { FTC_GNode gnode = (FTC_GNode)ftcgnode; FTC_FaceID face_id = (FTC_FaceID)ftcface_id; FTC_BasicFamily family = (FTC_BasicFamily)gnode->family; FT_Bool result; result = FT_BOOL( family->attrs.scaler.face_id == face_id ); if ( result ) { /* we must call this function to avoid this node from appearing * in later lookups with the same face_id! */ FTC_GNode_UnselectFamily( gnode, cache ); } return result; }
ftc_cmap_family_compare( FTC_CMapFamily cfam, FTC_CMapQuery cquery ) { FT_Int result = 0; /* first, compare face id and type */ if ( cfam->desc.face_id != cquery->desc->face_id || cfam->desc.type != cquery->desc->type ) goto Exit; switch ( cfam->desc.type ) { case FTC_CMAP_BY_INDEX: result = ( cfam->desc.u.index == cquery->desc->u.index ); break; case FTC_CMAP_BY_ENCODING: result = ( cfam->desc.u.encoding == cquery->desc->u.encoding ); break; case FTC_CMAP_BY_ID: result = ( cfam->desc.u.id.platform == cquery->desc->u.id.platform && cfam->desc.u.id.encoding == cquery->desc->u.id.encoding ); break; default: ; } if ( result ) { /* when found, update the 'family' and 'hash' field of the query */ FTC_QUERY( cquery )->family = FTC_FAMILY( cfam ); FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery ); } Exit: return FT_BOOL( result ); }
static FT_Bool ft_conic_is_small_enough( FT_Vector* base, FT_Angle *angle_in, FT_Angle *angle_out ) { FT_Vector d1, d2; FT_Angle theta; FT_Int close1, close2; d1.x = base[1].x - base[2].x; d1.y = base[1].y - base[2].y; d2.x = base[0].x - base[1].x; d2.y = base[0].y - base[1].y; close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); if ( close1 ) { if ( close2 ) *angle_in = *angle_out = 0; else *angle_in = *angle_out = FT_Atan2( d2.x, d2.y ); } else if ( close2 ) { *angle_in = *angle_out = FT_Atan2( d1.x, d1.y ); } else { *angle_in = FT_Atan2( d1.x, d1.y ); *angle_out = FT_Atan2( d2.x, d2.y ); } theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) ); return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD ); }
static FT_Bool gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage, FT_UShort* format, GXV_Validator valid ) { /* classic Microsoft-dialect */ FT_Bool horizontal; FT_Bool minimum; FT_Bool cross_stream; FT_Bool override; FT_UNUSED( valid ); /* reserved bits = 0 */ if ( coverage & 0xFDF0 ) return 0; horizontal = FT_BOOL( coverage & 1 ); minimum = FT_BOOL( ( coverage >> 1 ) & 1 ); cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 ); override = FT_BOOL( ( coverage >> 3 ) & 1 );
cff_font_load( FT_Stream stream, FT_Int face_index, CFF_Font font, FT_Bool pure_cff ) { static const FT_Frame_Field cff_header_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE CFF_FontRec FT_FRAME_START( 4 ), FT_FRAME_BYTE( version_major ), FT_FRAME_BYTE( version_minor ), FT_FRAME_BYTE( header_size ), FT_FRAME_BYTE( absolute_offsize ), FT_FRAME_END }; FT_Error error; FT_Memory memory = stream->memory; FT_ULong base_offset; CFF_FontRecDict dict; FT_ZERO( font ); font->stream = stream; font->memory = memory; dict = &font->top_font.font_dict; base_offset = FT_STREAM_POS(); /* read CFF font header */ if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) goto Exit; /* check format */ if ( font->version_major != 1 || font->header_size < 4 || font->absolute_offsize > 4 ) { FT_TRACE2(( "[not a CFF font header!]\n" )); error = CFF_Err_Unknown_File_Format; goto Exit; } /* skip the rest of the header */ if ( FT_STREAM_SKIP( font->header_size - 4 ) ) goto Exit; /* read the name, top dict, string and global subrs index */ if ( FT_SET_ERROR( cff_index_init( &font->name_index, stream, 0 ) ) || FT_SET_ERROR( cff_index_init( &font->font_dict_index, stream, 0 ) ) || FT_SET_ERROR( cff_index_init( &font->string_index, stream, 0 ) ) || FT_SET_ERROR( cff_index_init( &font->global_subrs_index, stream, 1 ) ) ) goto Exit; /* well, we don't really forget the `disabled' fonts... */ font->num_faces = font->name_index.count; if ( face_index >= (FT_Int)font->num_faces ) { FT_ERROR(( "cff_font_load: incorrect face index = %d\n", face_index )); error = CFF_Err_Invalid_Argument; } /* in case of a font format check, simply exit now */ if ( face_index < 0 ) goto Exit; /* now, parse the top-level font dictionary */ error = cff_subfont_load( &font->top_font, &font->font_dict_index, face_index, stream, base_offset ); if ( error ) goto Exit; if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) goto Exit; error = cff_index_init( &font->charstrings_index, stream, 0 ); if ( error ) goto Exit; /* now, check for a CID font */ if ( dict->cid_registry != 0xFFFFU ) { CFF_IndexRec fd_index; CFF_SubFont sub; FT_UInt idx; /* this is a CID-keyed font, we must now allocate a table of */ /* sub-fonts, then load each of them separately */ if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) goto Exit; error = cff_index_init( &fd_index, stream, 0 ); if ( error ) goto Exit; if ( fd_index.count > CFF_MAX_CID_FONTS ) { FT_ERROR(( "cff_font_load: FD array too large in CID font\n" )); goto Fail_CID; } /* allocate & read each font dict independently */ font->num_subfonts = fd_index.count; if ( FT_NEW_ARRAY( sub, fd_index.count ) ) goto Fail_CID; /* set up pointer table */ for ( idx = 0; idx < fd_index.count; idx++ ) font->subfonts[idx] = sub + idx; /* now load each subfont independently */ for ( idx = 0; idx < fd_index.count; idx++ ) { sub = font->subfonts[idx]; error = cff_subfont_load( sub, &fd_index, idx, stream, base_offset ); if ( error ) goto Fail_CID; } /* now load the FD Select array */ error = CFF_Load_FD_Select( &font->fd_select, font->charstrings_index.count, stream, base_offset + dict->cid_fd_select_offset ); Fail_CID: cff_index_done( &fd_index ); if ( error ) goto Exit; } else font->num_subfonts = 0; /* read the charstrings index now */ if ( dict->charstrings_offset == 0 ) { FT_ERROR(( "cff_font_load: no charstrings offset!\n" )); error = CFF_Err_Unknown_File_Format; goto Exit; } /* explicit the global subrs */ font->num_global_subrs = font->global_subrs_index.count; font->num_glyphs = font->charstrings_index.count; error = cff_index_get_pointers( &font->global_subrs_index, &font->global_subrs ) ; if ( error ) goto Exit; /* read the Charset and Encoding tables if available */ if ( font->num_glyphs > 0 ) { FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); error = cff_charset_load( &font->charset, font->num_glyphs, stream, base_offset, dict->charset_offset, invert ); if ( error ) goto Exit; /* CID-keyed CFFs don't have an encoding */ if ( dict->cid_registry == 0xFFFFU ) { error = cff_encoding_load( &font->encoding, &font->charset, font->num_glyphs, stream, base_offset, dict->encoding_offset ); if ( error ) goto Exit; } else /* CID-keyed fonts only need CIDs */ FT_FREE( font->charset.sids ); } /* get the font name (/CIDFontName for CID-keyed fonts, */ /* /FontName otherwise) */ font->font_name = cff_index_get_name( &font->name_index, face_index ); Exit: return error; }
pfr_face_init( FT_Stream stream, FT_Face pfrface, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { PFR_Face face = (PFR_Face)pfrface; FT_Error error; FT_UNUSED( num_params ); FT_UNUSED( params ); /* load the header and check it */ error = pfr_header_load( &face->header, stream ); if ( error ) goto Exit; if ( !pfr_header_check( &face->header ) ) { FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" )); error = PFR_Err_Unknown_File_Format; goto Exit; } /* check face index */ { FT_UInt num_faces; error = pfr_log_font_count( stream, face->header.log_dir_offset, &num_faces ); if ( error ) goto Exit; pfrface->num_faces = num_faces; } if ( face_index < 0 ) goto Exit; if ( face_index >= pfrface->num_faces ) { FT_ERROR(( "pfr_face_init: invalid face index\n" )); error = PFR_Err_Invalid_Argument; goto Exit; } /* load the face */ error = pfr_log_font_load( &face->log_font, stream, face_index, face->header.log_dir_offset, FT_BOOL( face->header.phy_font_max_size_high != 0 ) ); if ( error ) goto Exit; /* now load the physical font descriptor */ error = pfr_phy_font_load( &face->phy_font, stream, face->log_font.phys_offset, face->log_font.phys_size ); if ( error ) goto Exit; /* now, set-up all root face fields */ { PFR_PhyFont phy_font = &face->phy_font; pfrface->face_index = face_index; pfrface->num_glyphs = phy_font->num_chars; pfrface->face_flags = FT_FACE_FLAG_SCALABLE; if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; if ( phy_font->flags & PFR_PHY_VERTICAL ) pfrface->face_flags |= FT_FACE_FLAG_VERTICAL; else pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL; if ( phy_font->num_strikes > 0 ) pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES; if ( phy_font->num_kern_pairs > 0 ) pfrface->face_flags |= FT_FACE_FLAG_KERNING; /* If no family name was found in the "undocumented" auxiliary * data, use the font ID instead. This sucks but is better than * nothing. */ pfrface->family_name = phy_font->family_name; if ( pfrface->family_name == NULL ) pfrface->family_name = phy_font->font_id; /* note that the style name can be NULL in certain PFR fonts, * probably meaning "Regular" */ pfrface->style_name = phy_font->style_name; pfrface->num_fixed_sizes = 0; pfrface->available_sizes = 0; pfrface->bbox = phy_font->bbox; pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution; pfrface->ascender = (FT_Short) phy_font->bbox.yMax; pfrface->descender = (FT_Short) phy_font->bbox.yMin; pfrface->height = (FT_Short)( ( ( pfrface->ascender - pfrface->descender ) * 12 ) / 10 ); if ( phy_font->num_strikes > 0 ) { FT_UInt n, count = phy_font->num_strikes; FT_Bitmap_Size* size; PFR_Strike strike; FT_Memory memory = pfrface->stream->memory; if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) ) goto Exit; size = pfrface->available_sizes; strike = phy_font->strikes; for ( n = 0; n < count; n++, size++, strike++ ) { size->height = (FT_UShort)strike->y_ppm; size->width = (FT_UShort)strike->x_ppm; } pfrface->num_fixed_sizes = count; } /* now compute maximum advance width */ if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) pfrface->max_advance_width = (FT_Short)phy_font->standard_advance; else { FT_Int max = 0; FT_UInt count = phy_font->num_chars; PFR_Char gchar = phy_font->chars; for ( ; count > 0; count--, gchar++ ) { if ( max < gchar->advance ) max = gchar->advance; } pfrface->max_advance_width = (FT_Short)max; } pfrface->max_advance_height = pfrface->height; pfrface->underline_position = (FT_Short)( -pfrface->units_per_EM / 10 ); pfrface->underline_thickness = (FT_Short)( pfrface->units_per_EM / 30 ); /* create charmap */ { FT_CharMapRec charmap; charmap.face = pfrface; charmap.platform_id = 3; charmap.encoding_id = 1; charmap.encoding = FT_ENCODING_UNICODE; FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); #if 0 /* Select default charmap */ if ( pfrface->num_charmaps ) pfrface->charmap = pfrface->charmaps[0]; #endif } /* check whether we've loaded any kerning pairs */ if ( phy_font->num_kern_pairs ) pfrface->face_flags |= FT_FACE_FLAG_KERNING; } Exit: return error; }
pfr_slot_load( FT_GlyphSlot pfrslot, /* PFR_Slot */ FT_Size pfrsize, /* PFR_Size */ FT_UInt gindex, FT_Int32 load_flags ) { PFR_Slot slot = (PFR_Slot)pfrslot; PFR_Size size = (PFR_Size)pfrsize; FT_Error error; PFR_Face face = (PFR_Face)pfrslot->face; PFR_Char gchar; FT_Outline* outline = &pfrslot->outline; FT_ULong gps_offset; if ( gindex > 0 ) gindex--; /* check that the glyph index is correct */ FT_ASSERT( gindex < face->phy_font.num_chars ); /* try to load an embedded bitmap */ if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) { error = pfr_slot_load_bitmap( slot, size, gindex ); if ( error == 0 ) goto Exit; } if ( load_flags & FT_LOAD_SBITS_ONLY ) { error = PFR_Err_Invalid_Argument; goto Exit; } gchar = face->phy_font.chars + gindex; pfrslot->format = FT_GLYPH_FORMAT_OUTLINE; outline->n_points = 0; outline->n_contours = 0; gps_offset = face->header.gps_section_offset; /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */ error = pfr_glyph_load( &slot->glyph, face->root.stream, gps_offset, gchar->gps_offset, gchar->gps_size ); if ( !error ) { FT_BBox cbox; FT_Glyph_Metrics* metrics = &pfrslot->metrics; FT_Pos advance; FT_Int em_metrics, em_outline; FT_Bool scaling; scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); /* copy outline data */ *outline = slot->glyph.loader->base.outline; outline->flags &= ~FT_OUTLINE_OWNER; outline->flags |= FT_OUTLINE_REVERSE_FILL; if ( size && pfrsize->metrics.y_ppem < 24 ) outline->flags |= FT_OUTLINE_HIGH_PRECISION; /* compute the advance vector */ metrics->horiAdvance = 0; metrics->vertAdvance = 0; advance = gchar->advance; em_metrics = face->phy_font.metrics_resolution; em_outline = face->phy_font.outline_resolution; if ( em_metrics != em_outline ) advance = FT_MulDiv( advance, em_outline, em_metrics ); if ( face->phy_font.flags & PFR_PHY_VERTICAL ) metrics->vertAdvance = advance; else metrics->horiAdvance = advance; pfrslot->linearHoriAdvance = metrics->horiAdvance; pfrslot->linearVertAdvance = metrics->vertAdvance; /* make-up vertical metrics(?) */ metrics->vertBearingX = 0; metrics->vertBearingY = 0; /* Apply the font matrix, if any. */ /* TODO: Test existing fonts with unusual matrix */ /* whether we have to adjust Units per EM. */ { FT_Matrix font_matrix; font_matrix.xx = face->log_font.matrix[0] << 8; font_matrix.yx = face->log_font.matrix[1] << 8; font_matrix.xy = face->log_font.matrix[2] << 8; font_matrix.yy = face->log_font.matrix[3] << 8; FT_Outline_Transform( outline, &font_matrix ); } /* scale when needed */ if ( scaling ) { FT_Int n; FT_Fixed x_scale = pfrsize->metrics.x_scale; FT_Fixed y_scale = pfrsize->metrics.y_scale; FT_Vector* vec = outline->points; /* scale outline points */ for ( n = 0; n < outline->n_points; n++, vec++ ) { vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } /* scale the advance */ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); } /* compute the rest of the metrics */ FT_Outline_Get_CBox( outline, &cbox ); metrics->width = cbox.xMax - cbox.xMin; metrics->height = cbox.yMax - cbox.yMin; metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax - metrics->height; } Exit: return error; }
T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ FT_Size t1size, /* T1_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; FT_Error error; #ifdef __REACTOS__ T1_DecoderRec *decoder = malloc(sizeof(T1_DecoderRec)); /* Ugly but it allows us to reduce the diff */ #define decoder (*decoder) #else T1_DecoderRec decoder; #endif T1_Face face = (T1_Face)t1glyph->face; FT_Bool hinting; T1_Font type1 = &face->type1; PSAux_Service psaux = (PSAux_Service)face->psaux; const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; FT_Matrix font_matrix; FT_Vector font_offset; FT_Data glyph_data; FT_Bool must_finish_decoder = FALSE; #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Bool glyph_data_loaded = 0; #endif #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( glyph_index >= (FT_UInt)face->root.num_glyphs && !face->root.internal->incremental_interface ) #else if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { error = FT_THROW( Invalid_Argument ); goto Exit; } FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index )); FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; if ( t1size ) { glyph->x_scale = t1size->metrics.x_scale; glyph->y_scale = t1size->metrics.y_scale; } else { glyph->x_scale = 0x10000L; glyph->y_scale = 0x10000L; } t1glyph->outline.n_points = 0; t1glyph->outline.n_contours = 0; hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; error = decoder_funcs->init( &decoder, t1glyph->face, t1size, t1glyph, (FT_Byte**)type1->glyph_names, face->blend, FT_BOOL( hinting ), FT_LOAD_TARGET_MODE( load_flags ), T1_Parse_Glyph ); if ( error ) goto Exit; must_finish_decoder = TRUE; decoder.builder.no_recurse = FT_BOOL( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); decoder.num_subrs = type1->num_subrs; decoder.subrs = type1->subrs; decoder.subrs_len = type1->subrs_len; decoder.buildchar = face->buildchar; decoder.len_buildchar = face->len_buildchar; /* now load the unscaled outline */ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, &glyph_data ); if ( error ) goto Exit; #ifdef FT_CONFIG_OPTION_INCREMENTAL glyph_data_loaded = 1; #endif font_matrix = decoder.font_matrix; font_offset = decoder.font_offset; /* save new glyph tables */ decoder_funcs->done( &decoder ); must_finish_decoder = FALSE; /* now, set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax */ if ( !error ) { t1glyph->outline.flags &= FT_OUTLINE_OWNER; t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; /* for composite glyphs, return only left side bearing and */ /* advance width */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = t1glyph->internal; t1glyph->metrics.horiBearingX = FIXED_TO_INT( decoder.builder.left_bearing.x ); t1glyph->metrics.horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); internal->glyph_matrix = font_matrix; internal->glyph_delta = font_offset; internal->glyph_transformed = 1; } else { FT_BBox cbox; FT_Glyph_Metrics* metrics = &t1glyph->metrics; /* copy the _unscaled_ advance width */ metrics->horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->linearHoriAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->internal->glyph_transformed = 0; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { /* make up vertical ones */ metrics->vertAdvance = ( face->type1.font_bbox.yMax - face->type1.font_bbox.yMin ) >> 16; t1glyph->linearVertAdvance = metrics->vertAdvance; } else {
T1_Get_Private_Dict( T1_Parser parser, PSAux_Service psaux ) { FT_Stream stream = parser->stream; FT_Memory memory = parser->root.memory; FT_Error error = FT_Err_Ok; FT_ULong size; if ( parser->in_pfb ) { /* in the case of the PFB format, the private dictionary can be */ /* made of several segments. We thus first read the number of */ /* segments to compute the total size of the private dictionary */ /* then re-read them into memory. */ FT_ULong start_pos = FT_STREAM_POS(); FT_UShort tag; parser->private_len = 0; for (;;) { error = read_pfb_tag( stream, &tag, &size ); if ( error ) goto Fail; if ( tag != 0x8002U ) break; parser->private_len += size; if ( FT_STREAM_SKIP( size ) ) goto Fail; } /* Check that we have a private dictionary there */ /* and allocate private dictionary buffer */ if ( parser->private_len == 0 ) { FT_ERROR(( "T1_Get_Private_Dict:" " invalid private dictionary section\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } if ( FT_STREAM_SEEK( start_pos ) || FT_ALLOC( parser->private_dict, parser->private_len ) ) goto Fail; parser->private_len = 0; for (;;) { error = read_pfb_tag( stream, &tag, &size ); if ( error || tag != 0x8002U ) { error = FT_Err_Ok; break; } if ( FT_STREAM_READ( parser->private_dict + parser->private_len, size ) ) goto Fail; parser->private_len += size; } } else { /* We have already `loaded' the whole PFA font file into memory; */ /* if this is a memory resource, allocate a new block to hold */ /* the private dict. Otherwise, simply overwrite into the base */ /* dictionary block in the heap. */ /* first of all, look at the `eexec' keyword */ FT_Byte* cur = parser->base_dict; FT_Byte* limit = cur + parser->base_len; FT_Byte c; FT_Pointer pos_lf; FT_Bool test_cr; Again: for (;;) { c = cur[0]; if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ /* whitespace + 4 chars */ { if ( cur[1] == 'e' && cur[2] == 'x' && cur[3] == 'e' && cur[4] == 'c' ) break; } cur++; if ( cur >= limit ) { FT_ERROR(( "T1_Get_Private_Dict:" " could not find `eexec' keyword\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } } /* check whether `eexec' was real -- it could be in a comment */ /* or string (as e.g. in u003043t.gsf from ghostscript) */ parser->root.cursor = parser->base_dict; /* set limit to `eexec' + whitespace + 4 characters */ parser->root.limit = cur + 10; cur = parser->root.cursor; limit = parser->root.limit; while ( cur < limit ) { if ( *cur == 'e' && strncmp( (char*)cur, "eexec", 5 ) == 0 ) goto Found; T1_Skip_PS_Token( parser ); if ( parser->root.error ) break; T1_Skip_Spaces ( parser ); cur = parser->root.cursor; } /* we haven't found the correct `eexec'; go back and continue */ /* searching */ cur = limit; limit = parser->base_dict + parser->base_len; goto Again; /* now determine where to write the _encrypted_ binary private */ /* dictionary. We overwrite the base dictionary for disk-based */ /* resources and allocate a new block otherwise */ Found: parser->root.limit = parser->base_dict + parser->base_len; T1_Skip_PS_Token( parser ); cur = parser->root.cursor; limit = parser->root.limit; /* According to the Type 1 spec, the first cipher byte must not be */ /* an ASCII whitespace character code (blank, tab, carriage return */ /* or line feed). We have seen Type 1 fonts with two line feed */ /* characters... So skip now all whitespace character codes. */ /* */ /* On the other hand, Adobe's Type 1 parser handles fonts just */ /* fine that are violating this limitation, so we add a heuristic */ /* test to stop at \r only if it is not used for EOL. */ pos_lf = ft_memchr( cur, '\n', (size_t)( limit - cur ) ); test_cr = FT_BOOL( !pos_lf || pos_lf > ft_memchr( cur, '\r', (size_t)( limit - cur ) ) ); while ( cur < limit && ( *cur == ' ' || *cur == '\t' || (test_cr && *cur == '\r' ) || *cur == '\n' ) ) ++cur; if ( cur >= limit ) { FT_ERROR(( "T1_Get_Private_Dict:" " `eexec' not properly terminated\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } size = parser->base_len - (FT_ULong)( cur - parser->base_dict ); if ( parser->in_memory ) { /* note that we allocate one more byte to put a terminating `0' */ if ( FT_ALLOC( parser->private_dict, size + 1 ) ) goto Fail; parser->private_len = size; } else { parser->single_block = 1; parser->private_dict = parser->base_dict; parser->private_len = size; parser->base_dict = NULL; parser->base_len = 0; } /* now determine whether the private dictionary is encoded in binary */ /* or hexadecimal ASCII format -- decode it accordingly */ /* we need to access the next 4 bytes (after the final whitespace */ /* following the `eexec' keyword); if they all are hexadecimal */ /* digits, then we have a case of ASCII storage */ if ( cur + 3 < limit && ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) { /* ASCII hexadecimal encoding */ FT_ULong len; parser->root.cursor = cur; (void)psaux->ps_parser_funcs->to_bytes( &parser->root, parser->private_dict, parser->private_len, &len, 0 ); parser->private_len = len; /* put a safeguard */ parser->private_dict[len] = '\0'; } else /* binary encoding -- copy the private dict */ FT_MEM_MOVE( parser->private_dict, cur, size ); } /* we now decrypt the encoded binary private dictionary */ psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U ); if ( parser->private_len < 4 ) { FT_ERROR(( "T1_Get_Private_Dict:" " invalid private dictionary section\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } /* replace the four random bytes at the beginning with whitespace */ parser->private_dict[0] = ' '; parser->private_dict[1] = ' '; parser->private_dict[2] = ' '; parser->private_dict[3] = ' '; parser->root.base = parser->private_dict; parser->root.cursor = parser->private_dict; parser->root.limit = parser->root.cursor + parser->private_len; Fail: Exit: return error; }
sfnt_load_face(FT_Stream stream, TT_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter * params) { FT_Error error; #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES FT_Error psnames_error; #endif FT_Bool has_outline; FT_Bool is_apple_sbit; FT_Bool ignore_preferred_family = FALSE; FT_Bool ignore_preferred_subfamily = FALSE; SFNT_Service sfnt = (SFNT_Service)face->sfnt; FT_UNUSED(face_index); /* Check parameters */ { FT_Int i; for (i = 0; i < num_params; i++) { if (params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY) ignore_preferred_family = TRUE; else if (params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY) ignore_preferred_subfamily = TRUE; } } /* Load tables */ /* We now support two SFNT-based bitmapped font formats. They */ /* are recognized easily as they do not include a `glyf' */ /* table. */ /* */ /* The first format comes from Apple, and uses a table named */ /* `bhed' instead of `head' to store the font header (using */ /* the same format). It also doesn't include horizontal and */ /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ /* missing). */ /* */ /* The other format comes from Microsoft, and is used with */ /* WinCE/PocketPC. It looks like a standard TTF, except that */ /* it doesn't contain outlines. */ /* */ FT_TRACE2(("sfnt_load_face: %08p\n\n", face)); /* do we have outlines in there? */ #ifdef FT_CONFIG_OPTION_INCREMENTAL has_outline = FT_BOOL(face->root.internal->incremental_interface != 0 || tt_face_lookup_table(face, TTAG_glyf) != 0 || tt_face_lookup_table(face, TTAG_CFF) != 0); #else has_outline = FT_BOOL(tt_face_lookup_table(face, TTAG_glyf) != 0 || tt_face_lookup_table(face, TTAG_CFF) != 0); #endif is_apple_sbit = 0; /* if this font doesn't contain outlines, we try to load */ /* a `bhed' table */ if (!has_outline && sfnt->load_bhed) { LOAD_(bhed); is_apple_sbit = FT_BOOL(!error); } /* load the font header (`head' table) if this isn't an Apple */ /* sbit font file */ if (!is_apple_sbit) { LOAD_(head); if (error) goto Exit; } if (face->header.Units_Per_EM == 0) { error = SFNT_Err_Invalid_Table; goto Exit; } /* the following tables are often not present in embedded TrueType */ /* fonts within PDF documents, so don't check for them. */ LOAD_(maxp); LOAD_(cmap); /* the following tables are optional in PCL fonts -- */ /* don't check for errors */ LOAD_(name); LOAD_(post); #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES psnames_error = error; #endif /* do not load the metrics headers and tables if this is an Apple */ /* sbit font file */ if (!is_apple_sbit) { /* load the `hhea' and `hmtx' tables */ LOADM_(hhea, 0); if (!error) { LOADM_(hmtx, 0); if (error == SFNT_Err_Table_Missing) { error = SFNT_Err_Hmtx_Table_Missing; #ifdef FT_CONFIG_OPTION_INCREMENTAL /* If this is an incrementally loaded font and there are */ /* overriding metrics, tolerate a missing `hmtx' table. */ if (face->root.internal->incremental_interface && face->root.internal->incremental_interface->funcs-> get_glyph_metrics) { face->horizontal.number_Of_HMetrics = 0; error = SFNT_Err_Ok; } #endif } } else if (error == SFNT_Err_Table_Missing) { /* No `hhea' table necessary for SFNT Mac fonts. */ if (face->format_tag == TTAG_true) { FT_TRACE2(("This is an SFNT Mac font.\n")); has_outline = 0; error = SFNT_Err_Ok; } else { error = SFNT_Err_Horiz_Header_Missing; #ifdef FT_CONFIG_OPTION_INCREMENTAL /* If this is an incrementally loaded font and there are */ /* overriding metrics, tolerate a missing `hhea' table. */ if (face->root.internal->incremental_interface && face->root.internal->incremental_interface->funcs-> get_glyph_metrics) { face->horizontal.number_Of_HMetrics = 0; error = SFNT_Err_Ok; } #endif } } if (error) goto Exit; /* try to load the `vhea' and `vmtx' tables */ LOADM_(hhea, 1); if (!error) { LOADM_(hmtx, 1); if (!error) face->vertical_info = 1; } if (error && error != SFNT_Err_Table_Missing) goto Exit; LOAD_(os2); if (error) { if (error != SFNT_Err_Table_Missing) goto Exit; face->os2.version = 0xFFFFU; } } /* the optional tables */ /* embedded bitmap support */ if (sfnt->load_eblc) { LOAD_(eblc); if (error) { /* a font which contains neither bitmaps nor outlines is */ /* still valid (although rather useless in most cases); */ /* however, you can find such stripped fonts in PDFs */ if (error == SFNT_Err_Table_Missing) error = SFNT_Err_Ok; else goto Exit; } } LOAD_(pclt); if (error) { if (error != SFNT_Err_Table_Missing) goto Exit; face->pclt.Version = 0; } /* consider the kerning and gasp tables as optional */ LOAD_(gasp); LOAD_(kern); face->root.num_glyphs = face->max_profile.numGlyphs; /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ /* a WWS-only font face. `WWS' stands for `weight', width', and */ /* `slope', a term used by Microsoft's Windows Presentation */ /* Foundation (WPF). This flag has been introduced in version */ /* 1.5 of the OpenType specification (May 2008). */ face->root.family_name = NULL; face->root.style_name = NULL; if (face->os2.version != 0xFFFFU && face->os2.fsSelection & 256) { if (!ignore_preferred_family) GET_NAME(PREFERRED_FAMILY, &face->root.family_name); if (!face->root.family_name) GET_NAME(FONT_FAMILY, &face->root.family_name); if (!ignore_preferred_subfamily) GET_NAME(PREFERRED_SUBFAMILY, &face->root.style_name); if (!face->root.style_name) GET_NAME(FONT_SUBFAMILY, &face->root.style_name); } else { GET_NAME(WWS_FAMILY, &face->root.family_name); if (!face->root.family_name && !ignore_preferred_family) GET_NAME(PREFERRED_FAMILY, &face->root.family_name); if (!face->root.family_name) GET_NAME(FONT_FAMILY, &face->root.family_name); GET_NAME(WWS_SUBFAMILY, &face->root.style_name); if (!face->root.style_name && !ignore_preferred_subfamily) GET_NAME(PREFERRED_SUBFAMILY, &face->root.style_name); if (!face->root.style_name) GET_NAME(FONT_SUBFAMILY, &face->root.style_name); } /* now set up root fields */ { FT_Face root = &face->root; FT_Long flags = root->face_flags; /*********************************************************************/ /* */ /* Compute face flags. */ /* */ if (has_outline == TRUE) flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ /* The sfnt driver only supports bitmap fonts natively, thus we */ /* don't set FT_FACE_FLAG_HINTER. */ flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES if (psnames_error == SFNT_Err_Ok && face->postscript.FormatType != 0x00030000L) flags |= FT_FACE_FLAG_GLYPH_NAMES; #endif /* fixed width font? */ if (face->postscript.isFixedPitch) flags |= FT_FACE_FLAG_FIXED_WIDTH; /* vertical information? */ if (face->vertical_info) flags |= FT_FACE_FLAG_VERTICAL; /* kerning available ? */ if (TT_FACE_HAS_KERNING(face)) flags |= FT_FACE_FLAG_KERNING; #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT /* Don't bother to load the tables unless somebody asks for them. */ /* No need to do work which will (probably) not be used. */ if (tt_face_lookup_table(face, TTAG_glyf) != 0 && tt_face_lookup_table(face, TTAG_fvar) != 0 && tt_face_lookup_table(face, TTAG_gvar) != 0) flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; #endif root->face_flags = flags; /*********************************************************************/ /* */ /* Compute style flags. */ /* */ flags = 0; if (has_outline == TRUE && face->os2.version != 0xFFFFU) { /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ /* indicates an oblique font face. This flag has been */ /* introduced in version 1.5 of the OpenType specification. */ if (face->os2.fsSelection & 512) /* bit 9 */ flags |= FT_STYLE_FLAG_ITALIC; else if (face->os2.fsSelection & 1) /* bit 0 */ flags |= FT_STYLE_FLAG_ITALIC; if (face->os2.fsSelection & 32) /* bit 5 */ flags |= FT_STYLE_FLAG_BOLD; } else { /* this is an old Mac font, use the header field */ if (face->header.Mac_Style & 1) flags |= FT_STYLE_FLAG_BOLD; if (face->header.Mac_Style & 2) flags |= FT_STYLE_FLAG_ITALIC; } root->style_flags = flags; /*********************************************************************/ /* */ /* Polish the charmaps. */ /* */ /* Try to set the charmap encoding according to the platform & */ /* encoding ID of each charmap. */ /* */ tt_face_build_cmaps(face); /* ignore errors */ /* set the encoding fields */ { FT_Int m; for (m = 0; m < root->num_charmaps; m++) { FT_CharMap charmap = root->charmaps[m]; charmap->encoding = sfnt_find_encoding(charmap->platform_id, charmap->encoding_id); #if 0 if (root->charmap == NULL && charmap->encoding == FT_ENCODING_UNICODE) { /* set 'root->charmap' to the first Unicode encoding we find */ root->charmap = charmap; } #endif } } #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* * Now allocate the root array of FT_Bitmap_Size records and * populate them. Unfortunately, it isn't possible to indicate bit * depths in the FT_Bitmap_Size record. This is a design error. */ { FT_UInt i, count; #ifndef FT_CONFIG_OPTION_OLD_INTERNALS count = face->sbit_num_strikes; #else count = (FT_UInt)face->num_sbit_strikes; #endif if (count > 0) { FT_Memory memory = face->root.stream->memory; FT_UShort em_size = face->header.Units_Per_EM; FT_Short avgwidth = face->os2.xAvgCharWidth; FT_Size_Metrics metrics; if (em_size == 0 || face->os2.version == 0xFFFFU) { avgwidth = 0; em_size = 1; } if (FT_NEW_ARRAY(root->available_sizes, count)) goto Exit; for (i = 0; i < count; i++) { FT_Bitmap_Size *bsize = root->available_sizes + i; error = sfnt->load_strike_metrics(face, i, &metrics); if (error) goto Exit; bsize->height = (FT_Short)(metrics.height >> 6); bsize->width = (FT_Short)( (avgwidth * metrics.x_ppem + em_size / 2) / em_size); bsize->x_ppem = metrics.x_ppem << 6; bsize->y_ppem = metrics.y_ppem << 6; /* assume 72dpi */ bsize->size = metrics.y_ppem << 6; } root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; root->num_fixed_sizes = (FT_Int)count; } } #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* a font with no bitmaps and no outlines is scalable; */ /* it has only empty glyphs then */ if (!FT_HAS_FIXED_SIZES(root) && !FT_IS_SCALABLE(root)) root->face_flags |= FT_FACE_FLAG_SCALABLE; /*********************************************************************/ /* */ /* Set up metrics. */ /* */ if (FT_IS_SCALABLE(root)) { /* XXX What about if outline header is missing */ /* (e.g. sfnt wrapped bitmap)? */ root->bbox.xMin = face->header.xMin; root->bbox.yMin = face->header.yMin; root->bbox.xMax = face->header.xMax; root->bbox.yMax = face->header.yMax; root->units_per_EM = face->header.Units_Per_EM; /* XXX: Computing the ascender/descender/height is very different */ /* from what the specification tells you. Apparently, we */ /* must be careful because */ /* */ /* - not all fonts have an OS/2 table; in this case, we take */ /* the values in the horizontal header. However, these */ /* values very often are not reliable. */ /* */ /* - otherwise, the correct typographic values are in the */ /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ /* */ /* However, certain fonts have these fields set to 0. */ /* Rather, they have usWinAscent & usWinDescent correctly */ /* set (but with different values). */ /* */ /* As an example, Arial Narrow is implemented through four */ /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ /* */ /* Strangely, all fonts have the same values in their */ /* sTypoXXX fields, except ARIALNB which sets them to 0. */ /* */ /* On the other hand, they all have different */ /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ /* table cannot be used to compute the text height reliably! */ /* */ /* The ascender/descender/height are computed from the OS/2 table */ /* when found. Otherwise, they're taken from the horizontal */ /* header. */ /* */ root->ascender = face->horizontal.Ascender; root->descender = face->horizontal.Descender; root->height = (FT_Short)(root->ascender - root->descender + face->horizontal.Line_Gap); #if 0 /* if the line_gap is 0, we add an extra 15% to the text height -- */ /* this computation is based on various versions of Times New Roman */ if (face->horizontal.Line_Gap == 0) root->height = (FT_Short)((root->height * 115 + 50) / 100); #endif /* 0 */ #if 0 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */ /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */ if (face->os2.version != 0xFFFFU && root->ascender) { FT_Int height; root->ascender = face->os2.sTypoAscender; root->descender = -face->os2.sTypoDescender; height = root->ascender + root->descender + face->os2.sTypoLineGap; if (height > root->height) root->height = height; } #endif /* 0 */ root->max_advance_width = face->horizontal.advance_Width_Max; root->max_advance_height = (FT_Short)(face->vertical_info ? face->vertical.advance_Height_Max : root->height); /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ /* Adjust underline position from top edge to centre of */ /* stroke to convert TrueType meaning to FreeType meaning. */ root->underline_position = face->postscript.underlinePosition - face->postscript.underlineThickness / 2; root->underline_thickness = face->postscript.underlineThickness; } }
static FT_Error tt_face_get_name(TT_Face face, FT_UShort nameid, FT_String **name) { FT_Memory memory = face->root.memory; FT_Error error = SFNT_Err_Ok; FT_String *result = NULL; FT_UShort n; TT_NameEntryRec *rec; FT_Int found_apple = -1; FT_Int found_apple_roman = -1; FT_Int found_apple_english = -1; FT_Int found_win = -1; FT_Int found_unicode = -1; FT_Bool is_english = 0; TT_NameEntry_ConvertFunc convert; FT_ASSERT(name); rec = face->name_table.names; for (n = 0; n < face->num_names; n++, rec++) { /* According to the OpenType 1.3 specification, only Microsoft or */ /* Apple platform IDs might be used in the `name' table. The */ /* `Unicode' platform is reserved for the `cmap' table, and the */ /* `ISO' one is deprecated. */ /* */ /* However, the Apple TrueType specification doesn't say the same */ /* thing and goes to suggest that all Unicode `name' table entries */ /* should be coded in UTF-16 (in big-endian format I suppose). */ /* */ if (rec->nameID == nameid && rec->stringLength > 0) { switch (rec->platformID) { case TT_PLATFORM_APPLE_UNICODE: case TT_PLATFORM_ISO: /* there is `languageID' to check there. We should use this */ /* field only as a last solution when nothing else is */ /* available. */ /* */ found_unicode = n; break; case TT_PLATFORM_MACINTOSH: /* This is a bit special because some fonts will use either */ /* an English language id, or a Roman encoding id, to indicate */ /* the English version of its font name. */ /* */ if (rec->languageID == TT_MAC_LANGID_ENGLISH) found_apple_english = n; else if (rec->encodingID == TT_MAC_ID_ROMAN) found_apple_roman = n; break; case TT_PLATFORM_MICROSOFT: /* we only take a non-English name when there is nothing */ /* else available in the font */ /* */ if (found_win == -1 || (rec->languageID & 0x3FF) == 0x009) { switch (rec->encodingID) { case TT_MS_ID_SYMBOL_CS: case TT_MS_ID_UNICODE_CS: case TT_MS_ID_UCS_4: is_english = FT_BOOL((rec->languageID & 0x3FF) == 0x009); found_win = n; break; default: ; } } break; default: ; } } } found_apple = found_apple_roman; if (found_apple_english >= 0) found_apple = found_apple_english; /* some fonts contain invalid Unicode or Macintosh formatted entries; */ /* we will thus favor names encoded in Windows formats if available */ /* (provided it is an English name) */ /* */ convert = NULL; if (found_win >= 0 && !(found_apple >= 0 && !is_english)) { rec = face->name_table.names + found_win; switch (rec->encodingID) { /* all Unicode strings are encoded using UTF-16BE */ case TT_MS_ID_UNICODE_CS: case TT_MS_ID_SYMBOL_CS: convert = tt_name_entry_ascii_from_utf16; break; case TT_MS_ID_UCS_4: /* Apparently, if this value is found in a name table entry, it is */ /* documented as `full Unicode repertoire'. Experience with the */ /* MsGothic font shipped with Windows Vista shows that this really */ /* means UTF-16 encoded names (UCS-4 values are only used within */ /* charmaps). */ convert = tt_name_entry_ascii_from_utf16; break; default: ; } } else if (found_apple >= 0) { rec = face->name_table.names + found_apple; convert = tt_name_entry_ascii_from_other; } else if (found_unicode >= 0) { rec = face->name_table.names + found_unicode; convert = tt_name_entry_ascii_from_utf16; } if (rec && convert) { if (rec->string == NULL) { FT_Stream stream = face->name_table.stream; if (FT_QNEW_ARRAY (rec->string, rec->stringLength) || FT_STREAM_SEEK(rec->stringOffset) || FT_STREAM_READ(rec->string, rec->stringLength)) { FT_FREE(rec->string); rec->stringLength = 0; result = NULL; goto Exit; } } result = convert(rec, memory); } Exit: *name = result; return error; }
cff_slot_load( CFF_GlyphSlot glyph, CFF_Size size, FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Error error; CFF_Decoder decoder; PS_Decoder psdecoder; TT_Face face = (TT_Face)glyph->root.face; FT_Bool hinting, scaled, force_scaling; CFF_Font cff = (CFF_Font)face->extra.data; PSAux_Service psaux = (PSAux_Service)face->psaux; const CFF_Decoder_Funcs decoder_funcs = psaux->cff_decoder_funcs; FT_Matrix font_matrix; FT_Vector font_offset; force_scaling = FALSE; /* in a CID-keyed font, consider `glyph_index' as a CID and map */ /* it immediately to the real glyph_index -- if it isn't a */ /* subsetted font, glyph_indices and CIDs are identical, though */ if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && cff->charset.cids ) { /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ if ( glyph_index != 0 ) { glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index ); if ( glyph_index == 0 ) return FT_THROW( Invalid_Argument ); } } else if ( glyph_index >= cff->num_glyphs ) return FT_THROW( Invalid_Argument ); if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; glyph->x_scale = 0x10000L; glyph->y_scale = 0x10000L; if ( size ) { glyph->x_scale = size->root.metrics.x_scale; glyph->y_scale = size->root.metrics.y_scale; } #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* try to load embedded bitmap if any */ /* */ /* XXX: The convention should be emphasized in */ /* the documents because it can be confusing. */ if ( size ) { CFF_Face cff_face = (CFF_Face)size->root.face; SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; FT_Stream stream = cff_face->root.stream; if ( size->strike_index != 0xFFFFFFFFUL && sfnt->load_eblc && ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) { TT_SBit_MetricsRec metrics; error = sfnt->load_sbit_image( face, size->strike_index, glyph_index, (FT_UInt)load_flags, stream, &glyph->root.bitmap, &metrics ); if ( !error ) { FT_Bool has_vertical_info; FT_UShort advance; FT_Short dummy; glyph->root.outline.n_points = 0; glyph->root.outline.n_contours = 0; glyph->root.metrics.width = (FT_Pos)metrics.width << 6; glyph->root.metrics.height = (FT_Pos)metrics.height << 6; glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; glyph->root.format = FT_GLYPH_FORMAT_BITMAP; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { glyph->root.bitmap_left = metrics.vertBearingX; glyph->root.bitmap_top = metrics.vertBearingY; } else { glyph->root.bitmap_left = metrics.horiBearingX; glyph->root.bitmap_top = metrics.horiBearingY; } /* compute linear advance widths */ (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0, glyph_index, &dummy, &advance ); glyph->root.linearHoriAdvance = advance; has_vertical_info = FT_BOOL( face->vertical_info && face->vertical.number_Of_VMetrics > 0 ); /* get the vertical metrics from the vmtx table if we have one */ if ( has_vertical_info ) { (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1, glyph_index, &dummy, &advance ); glyph->root.linearVertAdvance = advance; } else { /* make up vertical ones */ if ( face->os2.version != 0xFFFFU ) glyph->root.linearVertAdvance = (FT_Pos) ( face->os2.sTypoAscender - face->os2.sTypoDescender ); else glyph->root.linearVertAdvance = (FT_Pos) ( face->horizontal.Ascender - face->horizontal.Descender ); } return error; } } } #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* return immediately if we only want the embedded bitmaps */ if ( load_flags & FT_LOAD_SBITS_ONLY ) return FT_THROW( Invalid_Argument ); /* if we have a CID subfont, use its matrix (which has already */ /* been multiplied with the root matrix) */ /* this scaling is only relevant if the PS hinter isn't active */ if ( cff->num_subfonts ) { FT_Long top_upm, sub_upm; FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); if ( fd_index >= cff->num_subfonts ) fd_index = (FT_Byte)( cff->num_subfonts - 1 ); top_upm = (FT_Long)cff->top_font.font_dict.units_per_em; sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em; font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; font_offset = cff->subfonts[fd_index]->font_dict.font_offset; if ( top_upm != sub_upm ) { glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); force_scaling = TRUE; } } else { font_matrix = cff->top_font.font_dict.font_matrix; font_offset = cff->top_font.font_dict.font_offset; } glyph->root.outline.n_points = 0; glyph->root.outline.n_contours = 0; /* top-level code ensures that FT_LOAD_NO_HINTING is set */ /* if FT_LOAD_NO_SCALE is active */ hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); glyph->hint = hinting; glyph->scaled = scaled; glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ { #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); #endif FT_Byte* charstring; FT_ULong charstring_len; decoder_funcs->init( &decoder, face, size, glyph, hinting, FT_LOAD_TARGET_MODE( load_flags ), cff_get_glyph_data, cff_free_glyph_data ); /* this is for pure CFFs */ if ( load_flags & FT_LOAD_ADVANCE_ONLY ) decoder.width_only = TRUE; decoder.builder.no_recurse = (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); /* now load the unscaled outline */ error = cff_get_glyph_data( face, glyph_index, &charstring, &charstring_len ); if ( error ) goto Glyph_Build_Finished; error = decoder_funcs->prepare( &decoder, size, glyph_index ); if ( error ) goto Glyph_Build_Finished; #ifdef CFF_CONFIG_OPTION_OLD_ENGINE /* choose which CFF renderer to use */ if ( driver->hinting_engine == FT_HINTING_FREETYPE ) error = decoder_funcs->parse_charstrings_old( &decoder, charstring, charstring_len, 0 ); else #endif { psaux->ps_decoder_init( &psdecoder, &decoder, FALSE ); error = decoder_funcs->parse_charstrings( &psdecoder, charstring, charstring_len ); /* Adobe's engine uses 16.16 numbers everywhere; */ /* as a consequence, glyphs larger than 2000ppem get rejected */ if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) { /* this time, we retry unhinted and scale up the glyph later on */ /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ /* 0x400 for both `x_scale' and `y_scale' in this case) */ hinting = FALSE; force_scaling = TRUE; glyph->hint = hinting; error = decoder_funcs->parse_charstrings( &psdecoder, charstring, charstring_len ); } } cff_free_glyph_data( face, &charstring, charstring_len ); if ( error ) goto Glyph_Build_Finished; #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Control data and length may not be available for incremental */ /* fonts. */ if ( face->root.internal->incremental_interface ) { glyph->root.control_data = NULL; glyph->root.control_len = 0; } else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ /* We set control_data and control_len if charstrings is loaded. */ /* See how charstring loads at cff_index_access_element() in */ /* cffload.c. */ { CFF_Index csindex = &cff->charstrings_index; if ( csindex->offsets ) { glyph->root.control_data = csindex->bytes + csindex->offsets[glyph_index] - 1; glyph->root.control_len = (FT_Long)charstring_len; } } Glyph_Build_Finished: /* save new glyph tables, if no error */ if ( !error ) decoder.builder.funcs.done( &decoder.builder ); /* XXX: anything to do for broken glyph entry? */ } #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts can optionally override the metrics. */ if ( !error && face->root.internal->incremental_interface && face->root.internal->incremental_interface->funcs->get_glyph_metrics ) { FT_Incremental_MetricsRec metrics; metrics.bearing_x = decoder.builder.left_bearing.x; metrics.bearing_y = 0; metrics.advance = decoder.builder.advance.x; metrics.advance_v = decoder.builder.advance.y; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, glyph_index, FALSE, &metrics ); decoder.builder.left_bearing.x = metrics.bearing_x; decoder.builder.advance.x = metrics.advance; decoder.builder.advance.y = metrics.advance_v; } #endif /* FT_CONFIG_OPTION_INCREMENTAL */ if ( !error ) { /* Now, set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax. */ /* For composite glyphs, return only left side bearing and */ /* advance width. */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = glyph->root.internal; glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; glyph->root.metrics.horiAdvance = decoder.glyph_width; internal->glyph_matrix = font_matrix; internal->glyph_delta = font_offset; internal->glyph_transformed = 1; } else { FT_BBox cbox; FT_Glyph_Metrics* metrics = &glyph->root.metrics; FT_Bool has_vertical_info; if ( face->horizontal.number_Of_HMetrics ) { FT_Short horiBearingX = 0; FT_UShort horiAdvance = 0; ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, glyph_index, &horiBearingX, &horiAdvance ); metrics->horiAdvance = horiAdvance; metrics->horiBearingX = horiBearingX; glyph->root.linearHoriAdvance = horiAdvance; } else { /* copy the _unscaled_ advance width */ metrics->horiAdvance = decoder.glyph_width; glyph->root.linearHoriAdvance = decoder.glyph_width; } glyph->root.internal->glyph_transformed = 0; has_vertical_info = FT_BOOL( face->vertical_info && face->vertical.number_Of_VMetrics > 0 ); /* get the vertical metrics from the vmtx table if we have one */ if ( has_vertical_info ) { FT_Short vertBearingY = 0; FT_UShort vertAdvance = 0; ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, glyph_index, &vertBearingY, &vertAdvance ); metrics->vertBearingY = vertBearingY; metrics->vertAdvance = vertAdvance; } else { /* make up vertical ones */ if ( face->os2.version != 0xFFFFU ) metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - face->os2.sTypoDescender ); else metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - face->horizontal.Descender ); } glyph->root.linearVertAdvance = metrics->vertAdvance; glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; glyph->root.outline.flags = 0; if ( size && size->root.metrics.y_ppem < 24 ) glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; /* apply the font matrix, if any */ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || font_matrix.xy != 0 || font_matrix.yx != 0 ) { FT_Outline_Transform( &glyph->root.outline, &font_matrix ); metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, font_matrix.xx ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, font_matrix.yy ); } if ( font_offset.x || font_offset.y ) { FT_Outline_Translate( &glyph->root.outline, font_offset.x, font_offset.y ); metrics->horiAdvance += font_offset.x; metrics->vertAdvance += font_offset.y; } if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) { /* scale the outline and the metrics */ FT_Int n; FT_Outline* cur = &glyph->root.outline; FT_Vector* vec = cur->points; FT_Fixed x_scale = glyph->x_scale; FT_Fixed y_scale = glyph->y_scale; /* First of all, scale the points */ if ( !hinting || !decoder.builder.hints_funcs ) for ( n = cur->n_points; n > 0; n--, vec++ ) { vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } /* Then scale the metrics */ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); } /* compute the other metrics */ FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); metrics->width = cbox.xMax - cbox.xMin; metrics->height = cbox.yMax - cbox.yMin; metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax; if ( has_vertical_info ) metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2; else { if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) ft_synthesize_vertical_metrics( metrics, metrics->vertAdvance ); } } } return error; }
/* reset the blues table when the device transform changes */ static void psh_blues_scale_zones( PSH_Blues blues, FT_Fixed scale, FT_Pos delta ) { FT_UInt count; FT_UInt num; PSH_Blue_Table table = 0; /* */ /* Determine whether we need to suppress overshoots or */ /* not. We simply need to compare the vertical scale */ /* parameter to the raw bluescale value. Here is why: */ /* */ /* We need to suppress overshoots for all pointsizes. */ /* At 300dpi that satisfies: */ /* */ /* pointsize < 240*bluescale + 0.49 */ /* */ /* This corresponds to: */ /* */ /* pixelsize < 1000*bluescale + 49/24 */ /* */ /* scale*EM_Size < 1000*bluescale + 49/24 */ /* */ /* However, for normal Type 1 fonts, EM_Size is 1000! */ /* We thus only check: */ /* */ /* scale < bluescale + 49/24000 */ /* */ /* which we shorten to */ /* */ /* "scale < bluescale" */ /* */ /* Note that `blue_scale' is stored 1000 times its real */ /* value, and that `scale' converts from font units to */ /* fractional pixels. */ /* */ /* 1000 / 64 = 125 / 8 */ if ( scale >= 0x20C49BAL ) blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 ); else blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 ); /* */ /* The blue threshold is the font units distance under */ /* which overshoots are suppressed due to the BlueShift */ /* even if the scale is greater than BlueScale. */ /* */ /* It is the smallest distance such that */ /* */ /* dist <= BlueShift && dist*scale <= 0.5 pixels */ /* */ { FT_Int threshold = blues->blue_shift; while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) threshold--; blues->blue_threshold = threshold; } for ( num = 0; num < 4; num++ ) { PSH_Blue_Zone zone; switch ( num ) { case 0: table = &blues->normal_top; break; case 1: table = &blues->normal_bottom; break; case 2: table = &blues->family_top; break; default: table = &blues->family_bottom; break; } zone = table->zones; count = table->count; for ( ; count > 0; count--, zone++ ) { zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta; zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta; zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta; zone->cur_delta = FT_MulFix( zone->org_delta, scale ); /* round scaled reference position */ zone->cur_ref = FT_PIX_ROUND( zone->cur_ref ); #if 0 if ( zone->cur_ref > zone->cur_top ) zone->cur_ref -= 64; else if ( zone->cur_ref < zone->cur_bottom ) zone->cur_ref += 64; #endif } } /* process the families now */ for ( num = 0; num < 2; num++ ) { PSH_Blue_Zone zone1, zone2; FT_UInt count1, count2; PSH_Blue_Table normal, family; switch ( num ) { case 0: normal = &blues->normal_top; family = &blues->family_top; break; default: normal = &blues->normal_bottom; family = &blues->family_bottom; } zone1 = normal->zones; count1 = normal->count; for ( ; count1 > 0; count1--, zone1++ ) { /* try to find a family zone whose reference position is less */ /* than 1 pixel far from the current zone */ zone2 = family->zones; count2 = family->count; for ( ; count2 > 0; count2--, zone2++ ) { FT_Pos Delta; Delta = zone1->org_ref - zone2->org_ref; if ( Delta < 0 ) Delta = -Delta; if ( FT_MulFix( Delta, scale ) < 64 ) { zone1->cur_top = zone2->cur_top; zone1->cur_bottom = zone2->cur_bottom; zone1->cur_ref = zone2->cur_ref; zone1->cur_delta = zone2->cur_delta; break; } } } } }
T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ FT_Size t1size, /* T1_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; FT_Error error; #ifdef __REACTOS__ T1_DecoderRec *decoder = malloc(sizeof(T1_DecoderRec)); if (!decoder) return FT_THROW( Out_Of_Memory ); /* Ugly but it allows us to reduce the diff */ #define decoder (*decoder) { #else T1_DecoderRec decoder; #endif T1_Face face = (T1_Face)t1glyph->face; FT_Bool hinting; FT_Bool scaled; FT_Bool force_scaling = FALSE; T1_Font type1 = &face->type1; PSAux_Service psaux = (PSAux_Service)face->psaux; const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; FT_Matrix font_matrix; FT_Vector font_offset; FT_Data glyph_data; FT_Bool must_finish_decoder = FALSE; #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Bool glyph_data_loaded = 0; #endif #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( glyph_index >= (FT_UInt)face->root.num_glyphs && !face->root.internal->incremental_interface ) #else if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { error = FT_THROW( Invalid_Argument ); goto Exit; } FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index )); FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; if ( t1size ) { glyph->x_scale = t1size->metrics.x_scale; glyph->y_scale = t1size->metrics.y_scale; } else { glyph->x_scale = 0x10000L; glyph->y_scale = 0x10000L; } t1glyph->outline.n_points = 0; t1glyph->outline.n_contours = 0; hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); glyph->hint = hinting; glyph->scaled = scaled; t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; error = decoder_funcs->init( &decoder, t1glyph->face, t1size, t1glyph, (FT_Byte**)type1->glyph_names, face->blend, FT_BOOL( hinting ), FT_LOAD_TARGET_MODE( load_flags ), T1_Parse_Glyph ); if ( error ) goto Exit; must_finish_decoder = TRUE; decoder.builder.no_recurse = FT_BOOL( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); decoder.num_subrs = type1->num_subrs; decoder.subrs = type1->subrs; decoder.subrs_len = type1->subrs_len; decoder.subrs_hash = type1->subrs_hash; decoder.buildchar = face->buildchar; decoder.len_buildchar = face->len_buildchar; /* now load the unscaled outline */ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, &glyph_data, &force_scaling ); if ( error ) goto Exit; #ifdef FT_CONFIG_OPTION_INCREMENTAL glyph_data_loaded = 1; #endif hinting = glyph->hint; font_matrix = decoder.font_matrix; font_offset = decoder.font_offset; /* save new glyph tables */ decoder_funcs->done( &decoder ); must_finish_decoder = FALSE; /* now, set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax */ if ( !error ) { t1glyph->outline.flags &= FT_OUTLINE_OWNER; t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; /* for composite glyphs, return only left side bearing and */ /* advance width */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = t1glyph->internal; t1glyph->metrics.horiBearingX = FIXED_TO_INT( decoder.builder.left_bearing.x ); t1glyph->metrics.horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); internal->glyph_matrix = font_matrix; internal->glyph_delta = font_offset; internal->glyph_transformed = 1; } else { FT_BBox cbox; FT_Glyph_Metrics* metrics = &t1glyph->metrics; /* copy the _unscaled_ advance width */ metrics->horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->linearHoriAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->internal->glyph_transformed = 0; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { /* make up vertical ones */ metrics->vertAdvance = ( face->type1.font_bbox.yMax - face->type1.font_bbox.yMin ) >> 16; t1glyph->linearVertAdvance = metrics->vertAdvance; } else { metrics->vertAdvance = FIXED_TO_INT( decoder.builder.advance.y ); t1glyph->linearVertAdvance = FIXED_TO_INT( decoder.builder.advance.y ); } t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; if ( t1size && t1size->metrics.y_ppem < 24 ) t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; #if 1 /* apply the font matrix, if any */ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || font_matrix.xy != 0 || font_matrix.yx != 0 ) { FT_Outline_Transform( &t1glyph->outline, &font_matrix ); metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, font_matrix.xx ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, font_matrix.yy ); } if ( font_offset.x || font_offset.y ) { FT_Outline_Translate( &t1glyph->outline, font_offset.x, font_offset.y ); metrics->horiAdvance += font_offset.x; metrics->vertAdvance += font_offset.y; } #endif if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) { /* scale the outline and the metrics */ FT_Int n; FT_Outline* cur = decoder.builder.base; FT_Vector* vec = cur->points; FT_Fixed x_scale = glyph->x_scale; FT_Fixed y_scale = glyph->y_scale; /* First of all, scale the points, if we are not hinting */ if ( !hinting || ! decoder.builder.hints_funcs ) for ( n = cur->n_points; n > 0; n--, vec++ ) { vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } /* Then scale the metrics */ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); } /* compute the other metrics */ FT_Outline_Get_CBox( &t1glyph->outline, &cbox ); metrics->width = cbox.xMax - cbox.xMin; metrics->height = cbox.yMax - cbox.yMin; metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { /* make up vertical ones */ ft_synthesize_vertical_metrics( metrics, metrics->vertAdvance ); } }
afm_parser_read_vals( AFM_Parser parser, AFM_Value vals, FT_UInt n ) { AFM_Stream stream = parser->stream; char* str; FT_UInt i; if ( n > AFM_MAX_ARGUMENTS ) return 0; for ( i = 0; i < n; i++ ) { FT_Offset len; AFM_Value val = vals + i; if ( val->type == AFM_VALUE_TYPE_STRING ) str = afm_stream_read_string( stream ); else str = afm_stream_read_one( stream ); if ( !str ) break; len = AFM_STREAM_KEY_LEN( stream, str ); switch ( val->type ) { case AFM_VALUE_TYPE_STRING: case AFM_VALUE_TYPE_NAME: { FT_Memory memory = parser->memory; FT_Error error; if ( !FT_QALLOC( val->u.s, len + 1 ) ) { ft_memcpy( val->u.s, str, len ); val->u.s[len] = '\0'; } } break; case AFM_VALUE_TYPE_FIXED: val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str, (FT_Byte*)str + len, 0 ); break; case AFM_VALUE_TYPE_INTEGER: val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str, (FT_Byte*)str + len ); break; case AFM_VALUE_TYPE_BOOL: val->u.b = FT_BOOL( len == 4 && !ft_strncmp( str, "true", 4 ) ); break; case AFM_VALUE_TYPE_INDEX: if ( parser->get_index ) val->u.i = parser->get_index( str, len, parser->user_data ); else val->u.i = 0; break; } } return i; }