rem: do_math_spacing(metrics, font, dvipsenc, cmap);
add: do_math_spacing(metrics, finfo, dvipsenc);
context: do_file(const String &otf_filename, const OpenType::Font &otf,	const DvipsEncoding &dvipsenc_in, bool dvipsenc_literal,	ErrorHandler *errh){    // get font    Cff cff(otf.table("CFF"), errh);    if (!cff.ok())	return;    Cff::FontParent *fp = cff.font(PermString(), errh);    if (!fp || !fp->ok())	return;    Cff::Font *font = dynamic_cast<Cff::Font *>(fp);    if (!font) {	errh->error("CID-keyed fonts not supported");	return;    }    // save glyph names    Vector<PermString> glyph_names;    font->glyph_names(glyph_names);    OpenType::debug_glyph_names = glyph_names;    // set typeface name from font family name    {	String typeface = font->dict_string(Cff::oFamilyName);	// make it reasonable for the shell	StringAccum sa;	for (int i = 0; i < typeface.length(); i++)	    if (isalnum(typeface[i]) || typeface[i] == '_' || typeface[i] == '-' || typeface[i] == '.' || typeface[i] == ',' || typeface[i] == '+')		sa << typeface[i];	set_typeface(sa.length() ? sa.take_string() : font_name, false);    }    // initialize encoding    DvipsEncoding dvipsenc(dvipsenc_in); // make copy    Metrics metrics(font, font->nglyphs());    OpenType::Cmap cmap(otf.table("cmap"), errh);    assert(cmap.ok());    if (dvipsenc_literal)	dvipsenc.make_metrics(metrics, cmap, font, 0, true, errh);    else {	T1Secondary secondary(font, cmap);	secondary.set_font_information(font_name, otf, otf_filename);	dvipsenc.make_metrics(metrics, cmap, font, &secondary, false, errh);    }    // encode boundary glyph at 256; pretend its Unicode value is '\n'    metrics.encode(256, '\n', metrics.boundary_glyph());    // maintain statistics about features    HashMap<uint32_t, int> feature_usage(0);    // apply activated GSUB features    try {	do_gsub(metrics, otf, dvipsenc, dvipsenc_literal, feature_usage, glyph_names, errh);    } catch (OpenType::BlankTable) {	// nada    } catch (OpenType::Error e) {	errh->warning("GSUB '%s' error, continuing", e.description.c_str());    }        // apply LIGKERN ligature commands to the result    dvipsenc.apply_ligkern_lig(metrics, errh);    // test fake ligature mechanism    //metrics.add_threeligature('T', 'h', 'e', '0');        // reencode characters to fit within 8 bytes (+ 1 for the boundary)    if (!dvipsenc_literal)	metrics.shrink_encoding(257, dvipsenc_in, errh);        // apply activated GPOS features    try {	do_gpos(metrics, otf, feature_usage, errh);    } catch (OpenType::BlankTable) {	// nada    } catch (OpenType::Error e) {	errh->warning("GPOS '%s' error, continuing", e.description.c_str());    }    // apply LIGKERN kerning commands to the result    dvipsenc.apply_ligkern_kern(metrics, errh);    // remove extra characters    metrics.cut_encoding(257);    //metrics.unparse();    int boundary_char = dvipsenc.boundary_char();    // apply letterspacing, if any    if (letterspace) {	for (int code = 0; code < 256; code++) {	    int g = metrics.glyph(code);	    if (g != 0 && g != Metrics::VIRTUAL_GLYPH && code != boundary_char) {		metrics.add_single_positioning(code, letterspace / 2, 0, letterspace);		metrics.add_kern(code, 256, -letterspace / 2);		metrics.add_kern(256, code, -letterspace / 2);	    }	}    }    // apply math letterspacing, if any    if (math_spacing)	do_math_spacing(metrics, font, dvipsenc, cmap);    // reencode right components of boundary_glyph as boundary_char    if (metrics.reencode_right_ligkern(256, boundary_char) > 0	&& boundary_char < 0) {	errh->warning("no boundary character, ignoring some ligatures and/or kerns\n");	errh->message("(You may want to try the --boundary-char option.)");    }    // report unused and underused features if any    report_underused_features(feature_usage, errh);    // figure out our FONTNAME    if (!font_name) {	// derive font name from OpenType font name	font_name = font->font_name();	if (encoding_file) {	    int slash = encoding_file.find_right('/') + 1;	    int dot = encoding_file.find_right('.');	    if (dot < slash)	// includes dot < 0 case		dot = encoding_file.length();	    font_name += String("--") + encoding_file.substring(slash, dot - slash);	}	if (interesting_scripts.size() != 2 || interesting_scripts[0] != OpenType::Tag("latn") || interesting_scripts[1].valid())	    for (int i = 0; i < interesting_scripts.size(); i += 2) {		font_name += String("--S") + interesting_scripts[i].text();		if (interesting_scripts[i+1].valid())		    font_name += String(".") + interesting_scripts[i+1].text();	    }	for (int i = 0; i < interesting_features.size(); i++)	    if (feature_usage[interesting_features[i].value()])		font_name += String("--F") + interesting_features[i].text();    }        // output encoding    if (dvipsenc_literal) {	out_encoding_name = dvipsenc_in.name();	out_encoding_file = dvipsenc_in.filename();    } else	output_encoding(metrics, glyph_names, errh);    // set up coding scheme    if (metrics.coding_scheme())	metrics.set_design_units(1);    else	metrics.set_coding_scheme(out_encoding_name);    // output    ::otf_filename = otf_filename;    output_metrics(metrics, font->font_name(), dvipsenc.boundary_char(),		   otf, font,		   out_encoding_name, out_encoding_file,		   font_name, main_dvips_map, errh);        // done    delete font;}