summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2018-06-11 11:25:39 +0000
committerTavmjong Bah <tavmjong@free.fr>2018-06-11 11:25:39 +0000
commit0fd518beb13ed45448492ecc782825412f2cff01 (patch)
treeb0d98e45c39028053fa30d31c431b7555de51c41 /src
parentMigrated object-test and sp-gradient-test to gtest (diff)
downloadinkscape-0fd518beb13ed45448492ecc782825412f2cff01.tar.gz
inkscape-0fd518beb13ed45448492ecc782825412f2cff01.zip
Improvements to the Font Features dialog. Better OpenType coverage.
Diffstat (limited to 'src')
-rw-r--r--src/libnrtype/FontInstance.cpp3
-rw-r--r--src/libnrtype/OpenTypeUtil.cpp136
-rw-r--r--src/libnrtype/OpenTypeUtil.h18
-rw-r--r--src/libnrtype/font-instance.h9
-rw-r--r--src/ui/widget/font-variants.cpp202
5 files changed, 223 insertions, 145 deletions
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index f8ee41108..667478924 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -211,8 +211,7 @@ void font_instance::InitTheFace()
#ifndef USE_PANGO_WIN32
- readOpenTypeGsubTable( theFace, openTypeTables, openTypeStylistic,
- openTypeLigatures, openTypeNumeric );
+ readOpenTypeGsubTable( theFace, openTypeTables );
readOpenTypeFvarAxes( theFace, openTypeVarAxes );
#if PANGO_VERSION_CHECK(1,41,1)
diff --git a/src/libnrtype/OpenTypeUtil.cpp b/src/libnrtype/OpenTypeUtil.cpp
index 9b7762d67..ffe0807b0 100644
--- a/src/libnrtype/OpenTypeUtil.cpp
+++ b/src/libnrtype/OpenTypeUtil.cpp
@@ -39,19 +39,31 @@ Glib::ustring extract_tag( guint32 *tag ) {
}
+void get_glyphs( hb_font_t* font, hb_set_t* set, Glib::ustring& characters) {
+
+ // There is a unicode to glyph mapping function but not the inverse!
+ hb_codepoint_t codepoint = -1;
+ while (hb_set_next (set, &codepoint)) {
+ for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) {
+ hb_codepoint_t glyph = 0;
+ hb_font_get_nominal_glyph (font, unicode_i, &glyph);
+ if (glyph == codepoint) {
+ characters += (gunichar)unicode_i;
+ continue;
+ }
+ }
+ }
+}
+
// Make a list of all tables found in the GSUB
// This list includes all tables regardless of script or language.
void readOpenTypeGsubTable (const FT_Face ft_face,
- std::map<Glib::ustring, int>& tables,
- std::map<Glib::ustring, Glib::ustring>& stylistic,
- std::map<Glib::ustring, Glib::ustring>& ligatures,
- std::map<Glib::ustring, Glib::ustring>& numerical
+ std::map<Glib::ustring, OTSubstitution>& tables
) {
+ // std::cout << "readOpenTypeGsubTable: Entrance: "
+ // << (ft_face->family_name?ft_face->family_name:"null") << std::endl;
tables.clear();
- stylistic.clear();
- ligatures.clear();
- numerical.clear();
// Use Harfbuzz, Pango's equivalent calls are deprecated.
auto const hb_face = hb_ft_face_create(ft_face, NULL);
@@ -64,6 +76,7 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, &script_count, hb_scripts);
for(unsigned int i = 0; i < script_count; ++i) {
+ // std::cout << " Script: " << extract_tag(&hb_scripts[i]) << std::endl;
auto language_count = hb_ot_layout_script_get_language_tags(hb_face, HB_OT_TAG_GSUB, i, 0, NULL, NULL);
if(language_count > 0) {
@@ -71,12 +84,14 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
hb_ot_layout_script_get_language_tags(hb_face, HB_OT_TAG_GSUB, i, 0, &language_count, hb_languages);
for(unsigned int j = 0; j < language_count; ++j) {
+ // std::cout << " Language: " << extract_tag(&hb_languages[j]) << std::endl;
auto feature_count = hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, j, 0, NULL, NULL);
auto const hb_features = g_new(hb_tag_t, feature_count + 1);
hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, j, 0, &feature_count, hb_features);
for(unsigned int k = 0; k < feature_count; ++k) {
- ++(tables[ extract_tag(&hb_features[k])]);
+ // std::cout << " Feature: " << extract_tag(&hb_features[k]) << std::endl;
+ tables[ extract_tag(&hb_features[k])];
}
g_free(hb_features);
@@ -87,6 +102,7 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
} else {
// Even if no languages are present there is still the default.
+ // std::cout << " Language: " << " (dflt)" << std::endl;
auto feature_count = hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
0, NULL, NULL);
@@ -96,7 +112,8 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
0, &feature_count, hb_features);
for(unsigned int k = 0; k < feature_count; ++k) {
- ++(tables[ extract_tag(&hb_features[k])]);
+ // std::cout << " Feature: " << extract_tag(&hb_features[k]) << std::endl;
+ tables[ extract_tag(&hb_features[k])];
}
g_free(hb_features);
@@ -116,6 +133,7 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
// Only look at style substitution tables ('salt', 'ss01', etc. but not 'ssty').
// Also look at character substitution tables ('cv01', etc.).
bool style =
+ table.first == "case" /* Case-Sensitive Forms */ ||
table.first == "salt" /* Stylistic Alternatives */ ||
table.first == "swsh" /* Swash */ ||
table.first == "cwsh" /* Contextual Swash */ ||
@@ -152,6 +170,7 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
table.first[3]),
&feature_index ) ) {
+ // std::cout << "Table: " << table.first << std::endl;
// std::cout << " Found feature, number: " << feature_index << std::endl;
unsigned int lookup_indexes[32];
unsigned int lookup_count = 32;
@@ -162,93 +181,56 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
lookup_indexes );
// std::cout << " Lookup count: " << count << " total: " << lookup_count << std::endl;
- if (count > 0) {
- hb_set_t* glyphs_before = NULL; // hb_set_create();
- hb_set_t* glyphs_input = hb_set_create(); // For stylistic
- hb_set_t* glyphs_after = NULL; // hb_set_create();
- hb_set_t* glyphs_output = hb_set_create(); // For ligatures
+ hb_font_t *hb_font = hb_font_create (hb_face); // MOVE THIS OUT OF LOOPS?
+
+ for (int i = 0; i < count; ++i) {
+ hb_set_t* glyphs_before = hb_set_create();
+ hb_set_t* glyphs_input = hb_set_create();
+ hb_set_t* glyphs_after = hb_set_create();
+ hb_set_t* glyphs_output = hb_set_create();
- // For now, just look at first index
hb_ot_layout_lookup_collect_glyphs (hb_face, HB_OT_TAG_GSUB,
- lookup_indexes[0],
+ lookup_indexes[i],
glyphs_before,
glyphs_input,
glyphs_after,
glyphs_output );
- hb_font_t *hb_font = hb_font_create (hb_face);
+ // std::cout << " Populations: "
+ // << " " << hb_set_get_population (glyphs_before)
+ // << " " << hb_set_get_population (glyphs_input)
+ // << " " << hb_set_get_population (glyphs_after)
+ // << " " << hb_set_get_population (glyphs_output)
+ // << std::endl;
// Without this, all functions return 0, etc.
hb_ft_font_set_funcs (hb_font);
- Glib::ustring unicode_characters;
-
- hb_codepoint_t codepoint = -1;
-
- if (style) {
- while (hb_set_next (glyphs_input, &codepoint)) {
-
- // There is a unicode to glyph mapping function but not the inverse!
- for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) {
- hb_codepoint_t glyph = 0;
- hb_font_get_nominal_glyph (hb_font, unicode_i, &glyph);
- if ( glyph == codepoint) {
- unicode_characters += (gunichar)unicode_i;
- continue;
- }
- }
- }
- stylistic[table.first] = unicode_characters;
- }
-
- // Don't know how to extract all input glyphs...
- // glyphs_input contains last input glyph, so just use output.
- if (ligature) {
- while (hb_set_next (glyphs_output, &codepoint)) {
-
- // There is a unicode to glyph mapping function but not the inverse!
- for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) {
- hb_codepoint_t glyph = 0;
- hb_font_get_nominal_glyph (hb_font, unicode_i, &glyph);
- if ( glyph == codepoint) {
- unicode_characters += (gunichar)unicode_i;
- unicode_characters += " "; // Add space
- continue;
- }
- }
- }
- ligatures[table.first] = unicode_characters;
- }
-
- if (numeric) {
- while (hb_set_next (glyphs_output, &codepoint)) {
-
- // There is a unicode to glyph mapping function but not the inverse!
- for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) {
- hb_codepoint_t glyph = 0;
- hb_font_get_nominal_glyph (hb_font, unicode_i, &glyph);
- if ( glyph == codepoint) {
- unicode_characters += (gunichar)unicode_i;
- unicode_characters += " "; // Add space
- continue;
- }
- }
- }
- numerical[table.first] = unicode_characters;
- }
+ get_glyphs (hb_font, glyphs_before, tables[table.first].before);
+ get_glyphs (hb_font, glyphs_input, tables[table.first].input );
+ get_glyphs (hb_font, glyphs_after, tables[table.first].after );
+ get_glyphs (hb_font, glyphs_output, tables[table.first].output);
+ // std::cout << " Before: " << tables[table.first].before.c_str() << std::endl;
+ // std::cout << " Input: " << tables[table.first].input.c_str() << std::endl;
+ // std::cout << " After: " << tables[table.first].after.c_str() << std::endl;
+ // std::cout << " Output: " << tables[table.first].output.c_str() << std::endl;
+
+ hb_set_destroy (glyphs_before);
hb_set_destroy (glyphs_input);
- hb_font_destroy (hb_font);
- }
+ hb_set_destroy (glyphs_after);
+ hb_set_destroy (glyphs_output);
+
+ } // End count (lookups)
+
+ hb_font_destroy (hb_font);
+
} else {
// std::cout << " Did not find '" << table.first << "'!" << std::endl;
}
}
}
- // for (auto table: res->openTypeSubstitutions) {
- // std::cout << table.first << ": " << table.second << std::endl;
- // }
#else
std::cerr << "Requires Harfbuzz 1.2.3 for visualizing alternative glyph OpenType tables. "
<< "Compiled with: " << HB_VERSION_STRING << "." << std::endl;
diff --git a/src/libnrtype/OpenTypeUtil.h b/src/libnrtype/OpenTypeUtil.h
index 9a792eb0e..0a249f123 100644
--- a/src/libnrtype/OpenTypeUtil.h
+++ b/src/libnrtype/OpenTypeUtil.h
@@ -18,6 +18,16 @@
* All three provide variable amounts of access to data.
*/
+// OpenType substitution
+class OTSubstitution {
+public:
+ OTSubstitution() {};
+ Glib::ustring before;
+ Glib::ustring input;
+ Glib::ustring after;
+ Glib::ustring output;
+};
+
// An OpenType fvar axis.
class OTVarAxis {
public:
@@ -53,11 +63,11 @@ inline FT_Fixed FTDoubleToFixed (double value) {
return static_cast<FT_Fixed>(value * 65536);
}
+// This would be better if one had std::vector<OTSubstitution> instead of OTSubstitution where each
+// entry corresponded to one substitution (e.g. ff -> ff) but Harfbuzz at the moment cannot return
+// individual substitutions. See Harfbuzz issue #673.
void readOpenTypeGsubTable (const FT_Face ft_face,
- std::map<Glib::ustring, int>& tables,
- std::map<Glib::ustring, Glib::ustring>& stylistic,
- std::map<Glib::ustring, Glib::ustring>& ligatures,
- std::map<Glib::ustring, Glib::ustring>& numeric);
+ std::map<Glib::ustring, OTSubstitution >& tables);
void readOpenTypeFvarAxes (const FT_Face ft_face,
std::map<Glib::ustring, OTVarAxis>& axes);
diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h
index ec26ba358..5cb26aec2 100644
--- a/src/libnrtype/font-instance.h
+++ b/src/libnrtype/font-instance.h
@@ -39,13 +39,8 @@ public:
int nbGlyph, maxGlyph;
font_glyph* glyphs;
- // Map of OpenType tables found in font (convert to std::set?)
- std::map<Glib::ustring, int> openTypeTables;
-
- // Map of substitutions indexed by table
- std::map<Glib::ustring, Glib::ustring> openTypeStylistic;
- std::map<Glib::ustring, Glib::ustring> openTypeLigatures;
- std::map<Glib::ustring, Glib::ustring> openTypeNumeric;
+ // Map of OpenType tables found in font.
+ std::map<Glib::ustring, OTSubstitution> openTypeTables;
// Maps for font variations.
std::map<Glib::ustring, OTVarAxis> openTypeVarAxes; // Axes with ranges
diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp
index 6d1da6d60..abe5add62 100644
--- a/src/ui/widget/font-variants.cpp
+++ b/src/ui/widget/font-variants.cpp
@@ -340,18 +340,19 @@ namespace Widget {
// Add tooltips
_feature_entry.set_tooltip_text( _("Feature settings in CSS form. No sanity checking is performed."));
- _feature_list.set_justify( Gtk::JUSTIFY_LEFT );
- _feature_list.set_line_wrap( true );
-
_feature_substitutions.set_justify( Gtk::JUSTIFY_LEFT );
_feature_substitutions.set_line_wrap( true );
_feature_substitutions.set_line_wrap_mode( Pango::WRAP_WORD_CHAR );
+ _feature_list.set_justify( Gtk::JUSTIFY_LEFT );
+ _feature_list.set_line_wrap( true );
+
// Add to frame
_feature_vbox.pack_start( _feature_entry );
_feature_vbox.pack_start( _feature_label );
- _feature_vbox.pack_start( _feature_list );
_feature_vbox.pack_start( _feature_substitutions );
+ _feature_vbox.pack_start( _feature_list );
+
_feature_frame.add( _feature_vbox );
pack_start( _feature_frame, Gtk::PACK_SHRINK );
@@ -582,7 +583,7 @@ namespace Widget {
font_instance* res = font_factory::Default()->FaceFromFontSpecification( font_spec.c_str() );
if( res ) {
- std::map<Glib::ustring,int>::iterator it;
+ std::map<Glib::ustring, OTSubstitution>::iterator it;
if((it = res->openTypeTables.find("liga"))!= res->openTypeTables.end() ||
(it = res->openTypeTables.find("clig"))!= res->openTypeTables.end()) {
@@ -767,20 +768,28 @@ namespace Widget {
Glib::ustring markup_dlig;
Glib::ustring markup_hlig;
Glib::ustring markup_calt;
- for (auto table: res->openTypeLigatures) {
-
- Glib::ustring markup;
- markup += "<span font_family='";
- markup += sp_font_description_get_family(res->descr);
- markup += "'>";
- markup += Glib::Markup::escape_text(table.second);
- markup += "</span>";
- if (table.first == "liga") markup_liga += markup;
- if (table.first == "clig") markup_liga += markup;
- if (table.first == "dlig") markup_dlig += markup;
- if (table.first == "hlig") markup_hlig += markup;
- if (table.first == "calt") markup_calt += markup;
+ for (auto table: res->openTypeTables) {
+
+ if (table.first == "liga" ||
+ table.first == "dlig" ||
+ table.first == "dlig" ||
+ table.first == "hgli" ||
+ table.first == "calt") {
+
+ Glib::ustring markup;
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second.output);
+ markup += "</span>";
+
+ if (table.first == "liga") markup_liga += markup;
+ if (table.first == "clig") markup_liga += markup;
+ if (table.first == "dlig") markup_dlig += markup;
+ if (table.first == "hlig") markup_hlig += markup;
+ if (table.first == "calt") markup_calt += markup;
+ }
}
_ligatures_label_common.set_markup ( markup_liga.c_str() );
@@ -797,7 +806,8 @@ namespace Widget {
Glib::ustring markup_afrc;
Glib::ustring markup_ordn;
Glib::ustring markup_zero;
- for (auto table: res->openTypeNumeric) {
+
+ for (auto table: res->openTypeTables) {
Glib::ustring markup;
markup += "<span font_family='";
@@ -810,7 +820,7 @@ namespace Widget {
table.first == "pnum" ||
table.first == "tnum") markup += "0123456789";
if (table.first == "zero") markup += "0";
- if (table.first == "ordn") markup += table.second;
+ if (table.first == "ordn") markup += "[" + table.second.before + "]" + table.second.output;
if (table.first == "frac" ||
table.first == "afrc" ) markup += "1/2 2/3 3/4 4/5 5/6"; // Can we do better?
markup += "</span>";
@@ -834,22 +844,24 @@ namespace Widget {
_numeric_ordinal_label.set_markup ( markup_ordn.c_str() );
_numeric_slashed_zero_label.set_markup ( markup_zero.c_str() );
- // Make list of tables not handled above... eventually add Gtk::Label with
- // this info.
- std::map<Glib::ustring,int> table_copy = res->openTypeTables;
+ // Make list of tables not handled above.
+ std::map<Glib::ustring, OTSubstitution> table_copy = res->openTypeTables;
if( (it = table_copy.find("liga")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("clig")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("dlig")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("hlig")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("calt")) != table_copy.end() ) table_copy.erase( it );
+
if( (it = table_copy.find("subs")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("sups")) != table_copy.end() ) table_copy.erase( it );
+
if( (it = table_copy.find("smcp")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("c2sc")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("pcap")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("c2pc")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("unic")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("titl")) != table_copy.end() ) table_copy.erase( it );
+
if( (it = table_copy.find("lnum")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("onum")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("pnum")) != table_copy.end() ) table_copy.erase( it );
@@ -858,6 +870,7 @@ namespace Widget {
if( (it = table_copy.find("afrc")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("ordn")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("zero")) != table_copy.end() ) table_copy.erase( it );
+
if( (it = table_copy.find("jp78")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("jp83")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("jp90")) != table_copy.end() ) table_copy.erase( it );
@@ -869,62 +882,141 @@ namespace Widget {
if( (it = table_copy.find("ruby")) != table_copy.end() ) table_copy.erase( it );
// An incomplete list of tables that should not be exposed to the user:
+ if( (it = table_copy.find("abvf")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("abvs")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("akhn")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("blwf")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("blws")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("ccmp")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("cjct")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("dnom")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("dtls")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("fina")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("half")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("haln")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("init")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("isol")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("locl")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("medi")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("nukt")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("numr")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("pref")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("pres")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("pstf")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("psts")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("rlig")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("rkrf")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("rphf")) != table_copy.end() ) table_copy.erase( it );
+ if( (it = table_copy.find("rtlm")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("ssty")) != table_copy.end() ) table_copy.erase( it );
if( (it = table_copy.find("vatu")) != table_copy.end() ) table_copy.erase( it );
+ std::string markup;
+
+ // GSUB lookup type 1 (1 to 1 mapping).
+ for (auto table: res->openTypeTables) {
+ if (table.first == "case" ||
+ table.first == "hist" ||
+ table.first[0] == 's' && table.first[1] == 's' && !(table.first[2] == 't')) {
+
+ if( (it = table_copy.find(table.first)) != table_copy.end() ) table_copy.erase( it );
+
+ markup += "<span font_weight='bold'>";
+ markup += table.first;
+ markup += "</span>";
+ markup += ": ";
+
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second.input);
+ markup += "</span>";
+
+ markup += " <span font_weight='bold'>→</span> ";
+
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += "<span font_features='";
+ markup += table.first;
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second.input);
+ markup += "</span>";
+ markup += "</span>\n";
+ }
+ }
+
+ // GSUB lookup type 3 (1 to many mapping). Optionally type 1.
+ for (auto table: res->openTypeTables) {
+ if (table.first == "salt" ||
+ table.first == "swsh" ||
+ table.first == "cwsh" ||
+ table.first == "ornm" ||
+ table.first == "nalt" ||
+ table.first[0] == 'c' && table.first[1] == 'v') {
+
+ if (table.second.input.length() == 0) {
+ // This can happen if a table is not in the 'DFLT' script and 'dflt' language.
+ // We should be using the 'lang' attribute to find the correct tables.
+ // std::cerr << "FontVariants::open_type_update: "
+ // << table.first << " has no entries!" << std::endl;
+ continue;
+ }
+
+ if( (it = table_copy.find(table.first)) != table_copy.end() ) table_copy.erase( it );
+
+ // Our lame attempt at determining number of alternative glyphs for one glyph:
+ int number = table.second.output.length() / table.second.input.length();
+
+ for (int i = 0; i < number; ++i) {
+ markup += "<span font_weight='bold'>";
+ markup += table.first;
+ if (i != 0) {
+ markup += " ";
+ markup += std::to_string (i + 1);
+ }
+ markup += "</span>";
+ markup += ": ";
+
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second.input);
+ markup += "</span>";
+
+ markup += " <span font_weight='bold'>→</span> ";
+
+ markup += "<span font_family='";
+ markup += sp_font_description_get_family(res->descr);
+ markup += "'>";
+ markup += "<span font_features='";
+ markup += table.first;
+ markup += " ";
+ markup += std::to_string (i + 1);
+ markup += "'>";
+ markup += Glib::Markup::escape_text(table.second.input);
+ markup += "</span>";
+ markup += "</span>\n";
+ }
+ }
+ }
+
+ _feature_substitutions.set_markup ( markup.c_str() );
+
std::string ott_list = "OpenType tables not included above: ";
for(it = table_copy.begin(); it != table_copy.end(); ++it) {
- // std::cout << "Other: " << it->first << " Occurrences: " << it->second << std::endl;
ott_list += it->first;
ott_list += ", ";
}
- _feature_list.set_text( ott_list.c_str() );
-
- // "<span foreground='darkblue'>";
- Glib::ustring markup;
-
- for (auto table: res->openTypeStylistic) {
-
- markup += "<span font_weight='bold'>";
- markup += table.first;
- markup += "</span>";
- markup += ": ";
-
- markup += "<span font_family='";
- markup += sp_font_description_get_family(res->descr);
- markup += "'>";
- markup += Glib::Markup::escape_text(table.second);
- markup += "</span>";
-
- markup += " → ";
-
- markup += "<span font_family='";
- markup += sp_font_description_get_family(res->descr);
- markup += "'>";
- markup += "<span font_features='";
- markup += table.first;
- markup += "'>";
- markup += Glib::Markup::escape_text(table.second);
- markup += "</span>";
- markup += "</span>\n";
-
+ if (table_copy.size() > 0) {
+ ott_list.pop_back();
+ ott_list.pop_back();
+ _feature_list.set_text( ott_list.c_str() );
+ } else {
+ _feature_list.set_text( "" );
}
- _feature_substitutions.set_markup ( markup.c_str() );
} else {
std::cerr << "FontVariants::update(): Couldn't find font_instance for: "