rem: && boundary_char < 0) errh->warning("no boundary character, removed some ligatures and/or kerns\n(You may want to try the --boundary-char option.)");
add: && 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.)"); }
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_literal_metrics(metrics, font);    else {	T1Secondary secondary(font, cmap);	secondary.set_font_information(font_name, otf, otf_filename);	dvipsenc.make_metrics(metrics, cmap, font, &secondary, errh);    }    // encode boundary glyph at 256    metrics.encode(256, metrics.boundary_glyph());        // maintain statistics about features    HashMap<uint32_t, int> feature_usage(0);        // apply activated GSUB features    OpenType::Gsub gsub(otf.table("GSUB"), errh);    Vector<Lookup> lookups(gsub.nlookups(), Lookup());    find_lookups(gsub.script_list(), gsub.feature_list(), lookups, errh);    Vector<OpenType::Substitution> subs;    for (int i = 0; i < lookups.size(); i++)	if (lookups[i].used) {	    OpenType::GsubLookup l = gsub.lookup(i);	    subs.clear();	    bool understood = l.unparse_automatics(gsub, subs);	    // check for -ffina, which should apply only at the ends of words,	    // and -finit, which should apply only at the beginnings.	    OpenType::Tag feature = (lookups[i].features.size() == 1 ? lookups[i].features[0] : OpenType::Tag());	    if (feature == OpenType::Tag("fina") || feature == OpenType::Tag("fin2") || feature == OpenType::Tag("fin3")) {		if (dvipsenc.boundary_char() < 0)		    errh->warning("'-ffina' requires a boundary character\n(The input encoding didn't specify a boundary character, but\nI need one to implement '-ffina' features correctly. Add one\nwith a \"%% LIGKERN || = <slot> ;\" command in the encoding.)");		else {		    int bg = metrics.boundary_glyph();		    for (int j = 0; j < subs.size(); j++)			subs[j].add_outer_right(bg);		}	    } else if (feature == OpenType::Tag("init")) {		int bg = metrics.boundary_glyph();		for (int j = 0; j < subs.size(); j++)		    subs[j].add_outer_left(bg);	    }	    //for (int subno = 0; subno < subs.size(); subno++) fprintf(stderr, "%5d\t%s\n", i, subs[subno].unparse().c_str());	    	    int nunderstood = metrics.apply(subs, !dvipsenc_literal, i, include_alternates, exclude_alternates, glyph_names);	    // mark as used	    int d = (understood && nunderstood == subs.size() ? F_GSUB_ALL : (nunderstood ? F_GSUB_PART : 0)) + F_GSUB_TRY;	    for (int j = 0; j < lookups[i].features.size(); j++)		feature_usage.find_force(lookups[i].features[j].value()) |= d;	}    // apply 'aalt' feature if we have variant selectors    if (metrics.altselectors() && !dvipsenc_literal) {	// apply default features	if (!altselector_features.size()) {	    altselector_features.push_back(OpenType::Tag("dlig"));	    altselector_features.push_back(OpenType::Tag("salt"));	}	// do lookups	altselector_features.swap(interesting_features);	Vector<Lookup> alt_lookups(gsub.nlookups(), Lookup());	find_lookups(gsub.script_list(), gsub.feature_list(), alt_lookups, ErrorHandler::silent_handler());	Vector<OpenType::Substitution> alt_subs;	for (int i = 0; i < alt_lookups.size(); i++)	    if (alt_lookups[i].used) {		OpenType::GsubLookup l = gsub.lookup(i);		alt_subs.clear();		(void) l.unparse_automatics(gsub, alt_subs);		metrics.apply_alternates(alt_subs, i, include_alternates, exclude_alternates, glyph_names);	    }	altselector_features.swap(interesting_features);    }        // 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    OpenType::Gpos gpos(otf.table("GPOS"), errh);    lookups.assign(gpos.nlookups(), Lookup());    find_lookups(gpos.script_list(), gpos.feature_list(), lookups, errh);    Vector<OpenType::Positioning> poss;    for (int i = 0; i < lookups.size(); i++)	if (lookups[i].used) {	    OpenType::GposLookup l = gpos.lookup(i);	    poss.clear();	    bool understood = l.unparse_automatics(poss);	    int nunderstood = metrics.apply(poss);	    // mark as used	    int d = (understood && nunderstood == poss.size() ? F_GPOS_ALL : (nunderstood ? F_GPOS_PART : 0)) + F_GPOS_TRY;	    for (int j = 0; j < lookups[i].features.size(); j++)		feature_usage.find_force(lookups[i].features[j].value()) |= d;	}    // apply LIGKERN kerning commands to the result    dvipsenc.apply_ligkern_kern(metrics, errh);    // remove extra characters    metrics.cut_encoding(257);    //metrics.unparse();    // 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 != dvipsenc.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);	    }	}    }    // reencode right components of boundary_glyph as boundary_char    int boundary_char = dvipsenc.boundary_char();    if (metrics.reencode_right_ligkern(256, boundary_char) > 0	&& boundary_char < 0)	errh->warning("no boundary character, removed some ligatures and/or kerns\n(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;}