summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2018-04-05 13:05:17 +0000
committerTavmjong Bah <tavmjong@free.fr>2018-04-05 13:05:17 +0000
commitc2fbc03b37ca44ad31db6503046a99c47a520313 (patch)
tree67df8583465fd6ef4c5bf0abf6d02edcf7a023d1 /src
parentReduce error messages. (diff)
downloadinkscape-c2fbc03b37ca44ad31db6503046a99c47a520313.tar.gz
inkscape-c2fbc03b37ca44ad31db6503046a99c47a520313.zip
Extract and display ligatures in a font.
Diffstat (limited to 'src')
-rw-r--r--src/libnrtype/FontFactory.cpp2
-rw-r--r--src/libnrtype/OpenTypeUtil.cpp71
-rw-r--r--src/libnrtype/OpenTypeUtil.h3
-rw-r--r--src/libnrtype/font-instance.h3
-rw-r--r--src/ui/widget/font-variants.cpp44
-rw-r--r--src/ui/widget/font-variants.h9
6 files changed, 101 insertions, 31 deletions
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 8cccd6ff3..98c9fa69f 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -705,7 +705,7 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail)
#ifndef USE_PANGO_WIN32
if (res) {
- readOpenTypeGsubTable( res->theFace, res->openTypeTables, res->openTypeSubstitutions );
+ readOpenTypeGsubTable( res->theFace, res->openTypeTables, res->openTypeStylistic, res->openTypeLigatures );
std::map<Glib::ustring, OTVarAxis> axes;
std::map<Glib::ustring, OTVarNamed> named;
readOpenTypeFvarTable( res->theFace, axes, named );
diff --git a/src/libnrtype/OpenTypeUtil.cpp b/src/libnrtype/OpenTypeUtil.cpp
index ba6fe8ec7..38b60c212 100644
--- a/src/libnrtype/OpenTypeUtil.cpp
+++ b/src/libnrtype/OpenTypeUtil.cpp
@@ -39,14 +39,17 @@ Glib::ustring extract_tag( guint32 *tag ) {
}
-// Make a list of all tables fount in the GSUB
+// 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>& substitutions) {
+ std::map<Glib::ustring, Glib::ustring>& stylistic,
+ std::map<Glib::ustring, Glib::ustring>& ligatures
+ ) {
tables.clear();
- substitutions.clear();
+ stylistic.clear();
+ ligatures.clear();
// Use Harfbuzz, Pango's equivalent calls are deprecated.
auto const hb_face = hb_ft_face_create(ft_face, NULL);
@@ -109,11 +112,16 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
for (auto table: tables) {
// Only look at style substitution tables ('salt', 'ss01', etc. but not 'ssty').
- if (table.first == "salt" ||
- (table.first[0] == 's' && table.first[1] == 's' && !(table.first[2] == 't') ) ) {
- // std::cout << " Table: " << table.first << std::endl;
+ bool style = table.first == "salt" ||
+ (table.first[0] == 's' && table.first[1] == 's' && !(table.first[2] == 't'));
- Glib::ustring unicode_characters;
+ bool ligature = ( table.first == "liga" || // Standard ligatures
+ table.first == "clig" || // Common ligatures
+ table.first == "dlig" || // Discretionary ligatures
+ table.first == "hlig" || // Historical ligatures
+ table.first == "calt" ); // Contextual alternatives
+
+ if (style || ligature ) {
unsigned int feature_index;
if ( hb_ot_layout_language_find_feature (hb_face, HB_OT_TAG_GSUB,
@@ -137,9 +145,9 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
if (count > 0) {
hb_set_t* glyphs_before = NULL; // hb_set_create();
- hb_set_t* glyphs_input = 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 = NULL; // hb_set_create();
+ hb_set_t* glyphs_output = hb_set_create(); // For ligatures
// For now, just look at first index
hb_ot_layout_lookup_collect_glyphs (hb_face, HB_OT_TAG_GSUB,
@@ -154,20 +162,44 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
// Without this, all functions return 0, etc.
hb_ft_font_set_funcs (hb_font);
+ Glib::ustring unicode_characters;
+
hb_codepoint_t codepoint = -1;
- 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;
+
+ 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;
}
- substitutions[table.first] = unicode_characters;
hb_set_destroy (glyphs_input);
hb_font_destroy (hb_font);
@@ -176,6 +208,7 @@ void readOpenTypeGsubTable (const FT_Face ft_face,
// std::cout << " Did not find '" << table.first << "'!" << std::endl;
}
}
+
}
// for (auto table: res->openTypeSubstitutions) {
// std::cout << table.first << ": " << table.second << std::endl;
diff --git a/src/libnrtype/OpenTypeUtil.h b/src/libnrtype/OpenTypeUtil.h
index 5c0780492..b4f7593dd 100644
--- a/src/libnrtype/OpenTypeUtil.h
+++ b/src/libnrtype/OpenTypeUtil.h
@@ -50,7 +50,8 @@ inline FT_Fixed FTDoubleToFixed (double value) {
void readOpenTypeGsubTable (const FT_Face ft_face,
std::map<Glib::ustring, int>& tables,
- std::map<Glib::ustring, Glib::ustring>& substitutions);
+ std::map<Glib::ustring, Glib::ustring>& stylistic,
+ std::map<Glib::ustring, Glib::ustring>& ligatures);
void readOpenTypeFvarTable (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 ee23ff62d..f6408eccb 100644
--- a/src/libnrtype/font-instance.h
+++ b/src/libnrtype/font-instance.h
@@ -39,7 +39,8 @@ public:
std::map<Glib::ustring, int> openTypeTables;
// Map of substitutions indexed by table
- std::map<Glib::ustring, Glib::ustring> openTypeSubstitutions;
+ std::map<Glib::ustring, Glib::ustring> openTypeStylistic;
+ std::map<Glib::ustring, Glib::ustring> openTypeLigatures;
font_instance(void);
virtual ~font_instance(void);
diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp
index 6d072602f..ac464e1d6 100644
--- a/src/ui/widget/font-variants.cpp
+++ b/src/ui/widget/font-variants.cpp
@@ -2,7 +2,7 @@
* Author:
* Tavmjong Bah <tavmjong@free.fr>
*
- * Copyright (C) 2015 Tavmong Bah
+ * Copyright (C) 2015, 2018 Tavmong Bah
*
* Released under GNU GPL. Read the file 'COPYING' for more information.
*/
@@ -90,11 +90,15 @@ namespace Widget {
_ligatures_contextual.signal_clicked().connect ( sigc::mem_fun(*this, &FontVariants::ligatures_callback) );
// Add to frame
- _ligatures_vbox.pack_start( _ligatures_common );
- _ligatures_vbox.pack_start( _ligatures_discretionary );
- _ligatures_vbox.pack_start( _ligatures_historical );
- _ligatures_vbox.pack_start( _ligatures_contextual );
- _ligatures_frame.add( _ligatures_vbox );
+ _ligatures_grid.attach( _ligatures_common, 0, 0, 1, 1);
+ _ligatures_grid.attach( _ligatures_discretionary, 0, 1, 1, 1);
+ _ligatures_grid.attach( _ligatures_historical, 0, 2, 1, 1);
+ _ligatures_grid.attach( _ligatures_contextual, 0, 3, 1, 1);
+ _ligatures_grid.attach( _ligatures_label_common, 1, 0, 1, 1);
+ _ligatures_grid.attach( _ligatures_label_discretionary, 1, 1, 1, 1);
+ _ligatures_grid.attach( _ligatures_label_historical, 1, 2, 1, 1);
+ _ligatures_grid.attach( _ligatures_label_contextual, 1, 3, 1, 1);
+ _ligatures_frame.add( _ligatures_grid );
pack_start( _ligatures_frame, Gtk::PACK_SHRINK );
ligatures_init();
@@ -539,6 +543,32 @@ namespace Widget {
_numeric_slashed_zero.set_sensitive( false );
}
+ // List available ligatures
+ Glib::ustring markup_liga;
+ 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;
+ }
+
+ _ligatures_label_common.set_markup ( markup_liga.c_str() );
+ _ligatures_label_discretionary.set_markup ( markup_dlig.c_str() );
+ _ligatures_label_historical.set_markup ( markup_hlig.c_str() );
+ _ligatures_label_contextual.set_markup ( markup_calt.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;
@@ -574,7 +604,7 @@ namespace Widget {
// "<span foreground='darkblue'>";
Glib::ustring markup;
- for (auto table: res->openTypeSubstitutions) {
+ for (auto table: res->openTypeStylistic) {
markup += table.first;
markup += ": ";
diff --git a/src/ui/widget/font-variants.h b/src/ui/widget/font-variants.h
index 96cab91b2..e7330b6cc 100644
--- a/src/ui/widget/font-variants.h
+++ b/src/ui/widget/font-variants.h
@@ -2,7 +2,7 @@
* Author:
* Tavmjong Bah <tavmjong@free.fr>
*
- * Copyright (C) 2015 Tavmong Bah
+ * Copyright (C) 2015, 2018 Tavmong Bah
*
* Released under GNU GPL. Read the file 'COPYING' for more information.
*/
@@ -14,6 +14,7 @@
#include <gtkmm/checkbutton.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/entry.h>
+#include <gtkmm/grid.h>
class SPDesktop;
class SPObject;
@@ -40,11 +41,15 @@ public:
protected:
// To start, use four check buttons.
Gtk::Expander _ligatures_frame;
- Gtk::VBox _ligatures_vbox;
+ Gtk::Grid _ligatures_grid;
Gtk::CheckButton _ligatures_common;
Gtk::CheckButton _ligatures_discretionary;
Gtk::CheckButton _ligatures_historical;
Gtk::CheckButton _ligatures_contextual;
+ Gtk::Label _ligatures_label_common;
+ Gtk::Label _ligatures_label_discretionary;
+ Gtk::Label _ligatures_label_historical;
+ Gtk::Label _ligatures_label_contextual;
// Exclusive options
Gtk::Expander _position_frame;