summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-01-03 14:23:33 -0500
committerMatthias Clasen <mclasen@redhat.com>2018-01-03 14:56:36 -0500
commitebeca18635a0d7f658b0f6eb2a0af186c78365bb (patch)
tree9dba5b42eda8e0001b45dbbc8ac51a3c8231ed20
parent83c5b661f668506119302b0eab039b2108eaf2f0 (diff)
downloadgtk+-ebeca18635a0d7f658b0f6eb2a0af186c78365bb.tar.gz
gtk-demo: Update font explorer example
Revise the UI (no more double checkboxes), add font variations, update font features from the dialog, allow tweaking ranges.
-rw-r--r--demos/gtk-demo/demo.gresource.xml2
-rw-r--r--demos/gtk-demo/font-features.ui1541
-rw-r--r--demos/gtk-demo/font_features.c1652
-rw-r--r--demos/gtk-demo/fontplane.c315
-rw-r--r--demos/gtk-demo/fontplane.h65
-rw-r--r--demos/gtk-demo/language-names.c233
-rw-r--r--demos/gtk-demo/language-names.h13
-rw-r--r--demos/gtk-demo/meson.build2
-rw-r--r--demos/gtk-demo/script-names.c184
-rw-r--r--demos/gtk-demo/script-names.h13
10 files changed, 2373 insertions, 1647 deletions
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index 4539b40499..2d69cdad78 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -163,6 +163,7 @@
<file>flowbox.c</file>
<file>foreigndrawing.c</file>
<file>font_features.c</file>
+ <file>fontplane.c</file>
<file>gestures.c</file>
<file>glarea.c</file>
<file>headerbar.c</file>
@@ -224,6 +225,7 @@
</gresource>
<gresource prefix="/font_features">
<file>font-features.ui</file>
+ <file>fontplane.c</file>
</gresource>
<gresource prefix="/spinbutton">
<file>spinbutton.ui</file>
diff --git a/demos/gtk-demo/font-features.ui b/demos/gtk-demo/font-features.ui
index aae2615558..3a88e769f7 100644
--- a/demos/gtk-demo/font-features.ui
+++ b/demos/gtk-demo/font-features.ui
@@ -9,18 +9,18 @@
<object class="GtkHeaderBar">
<property name="visible">1</property>
<property name="show-title-buttons">1</property>
- <property name="title">Font Features</property>
+ <property name="title">Font Explorer</property>
<child>
<object class="GtkButton" id="reset">
<property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="receives_default">1</property>
+ <property name="can-focus">1</property>
+ <property name="receives-default">1</property>
<property name="tooltip-text">Reset</property>
<signal name="clicked" handler="reset" swapped="no"/>
<child>
<object class="GtkImage">
<property name="visible">1</property>
- <property name="icon_name">view-refresh-symbolic</property>
+ <property name="icon-name">view-refresh-symbolic</property>
</object>
</child>
</object>
@@ -33,8 +33,8 @@
<child>
<object class="GtkScrolledWindow">
<property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="hscrollbar_policy">never</property>
+ <property name="can-focus">1</property>
+ <property name="hscrollbar-policy">never</property>
<child>
<object class="GtkViewport">
<property name="visible">1</property>
@@ -47,218 +47,40 @@
<child>
<object class="GtkFontButton" id="font">
<property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="receives_default">1</property>
+ <property name="can-focus">1</property>
+ <property name="receives-default">1</property>
<property name="font">Sans 12</property>
<signal name="font-set" handler="font_changed" swapped="no"/>
</object>
</child>
<child>
- <object class="GtkComboBox" id="script_lang">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <signal name="changed" handler="script_changed" swapped="no"/>
- <child>
- <object class="GtkCellRendererText"/>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
- </object>
- </child>
- <child>
<object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="kern_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="kern_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="kern">
- <property name="label" translatable="yes">Enabled</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="kern_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
<child type="label">
<object class="GtkLabel">
<property name="visible">1</property>
- <property name="label" translatable="yes">Kerning</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Font Features</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
</child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
<child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
+ <object class="GtkBox" id="feature_list">
<property name="orientation">vertical</property>
<child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="liga_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
+ <object class="GtkComboBox" id="script_lang">
+ <property name="can-focus">1</property>
+ <property name="margin-top">10</property>
+ <signal name="changed" handler="script_changed" swapped="no"/>
<child>
- <object class="GtkCheckButton" id="liga_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="liga">
- <property name="label" translatable="yes">Common Ligatures</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="liga_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
+ <object class="GtkCellRendererText"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
</child>
</object>
</child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="dlig_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="dlig_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="dlig">
- <property name="label" translatable="yes">Discretionary Ligatures</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="dlig_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="hlig_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="hlig_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="hlig">
- <property name="label" translatable="yes">Historical Ligatures</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="hlig_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="clig_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="clig_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="clig">
- <property name="label" translatable="yes">Contextual Ligatures</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="clig_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Ligatures</property>
</object>
</child>
</object>
@@ -266,1273 +88,21 @@
<child>
<object class="GtkExpander">
<property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="smcp_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="smcp_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="smcp">
- <property name="label" translatable="yes">Small Caps</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="valign">baseline</property>
- <property name="sensitive" bind-source="smcp_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="c2sc_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="c2sc_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="c2sc">
- <property name="label" translatable="yes">Small Caps from Caps</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="c2sc_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="pcap_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="pcap_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="pcap">
- <property name="label" translatable="yes">Petite Caps</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="pcap_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="c2pc_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="c2pc_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="c2pc">
- <property name="label" translatable="yes">Caps to Petite Caps</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="c2pc_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="unic_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="unic_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="unic">
- <property name="label" translatable="yes">Unicase</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="unic_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="cpsp_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="cpsp_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="cpsp">
- <property name="label" translatable="yes">Capital Spacing</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="cpsp_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="case_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="case_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="case">
- <property name="label" translatable="yes">Case-sensitive Forms</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="case_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
<child type="label">
- <object class="GtkLabel">
+ <object class="GtkLabel" id="variations_heading">
<property name="visible">1</property>
- <property name="label" translatable="yes">Letter Case</property>
+ <property name="label" translatable="yes">Font Variations</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
</object>
</child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
<child>
- <object class="GtkBox">
+ <object class="GtkGrid" id="variations_grid">
<property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="numcasedefault_pres">
- <property name="visible">1</property>
- <property name="opacity">0</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="numcasedefault">
- <property name="label" translatable="yes">Default</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="lnum_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="lnum">
- <property name="label" translatable="yes">Lining</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <property name="group">numcasedefault</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="onum_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="onum">
- <property name="label" translatable="yes">Old-Style</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="valign">baseline</property>
- <property name="draw_indicator">1</property>
- <property name="group">numcasedefault</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Number Case</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="numspacedefault_pres">
- <property name="visible">1</property>
- <property name="opacity">0</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="numspacedefault">
- <property name="label" translatable="yes">Default</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="pnum_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="pnum">
- <property name="label" translatable="yes">Proportional</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="group">numspacedefault</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="tnum_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="tnum">
- <property name="label" translatable="yes">Tabular</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="group">numspacedefault</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Number Spacing</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="fractiondefault_pres">
- <property name="visible">1</property>
- <property name="opacity">0</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="fractiondefault">
- <property name="label" translatable="yes">Off</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="frac_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="frac">
- <property name="label" translatable="yes">Normal</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="group">fractiondefault</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="afrc_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkRadioButton" id="afrc">
- <property name="label" translatable="yes">Alternate</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="active">1</property>
- <property name="draw_indicator">1</property>
- <property name="group">fractiondefault</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Fractions</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="zero_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="zero_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="zero">
- <property name="label" translatable="yes">Slashed Zero</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="zero_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="nalt_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="nalt_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="nalt">
- <property name="label" translatable="yes">Alternative Annotations</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="nalt_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="sinf_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="sinf_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="sinf">
- <property name="label" translatable="yes">Scientific Inferiors</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="sinf_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Numeric Extras</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="swsh_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="swsh_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="swsh">
- <property name="label" translatable="yes">Swash Glyphs</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="swsh_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="cswh_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="cswh_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="cswh">
- <property name="label" translatable="yes">Contextual Swash</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="cswh_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="locl_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="locl_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="locl">
- <property name="label" translatable="yes">Localized Forms</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="locl_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="calt_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="calt_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="calt">
- <property name="label" translatable="yes">Contextual Alternatives</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="calt_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="hist_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="hist_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="hist">
- <property name="label" translatable="yes">Historical Alternatives</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="hist_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="salt_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="salt_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="salt">
- <property name="label" translatable="yes">Stylistic Alternatives</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="salt_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="titl_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="titl_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="titl">
- <property name="label" translatable="yes">Titling Alternatives</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="titl_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="rand_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="rand_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="rand">
- <property name="label" translatable="yes">Randomize</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="rand_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="subs_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="subs_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="subs">
- <property name="label" translatable="yes">Subscript</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="subs_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="sups_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="sups_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="sups">
- <property name="label" translatable="yes">Superscript</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="sups_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Character Alternatives</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="init_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="init_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="init">
- <property name="label" translatable="yes">Initial Forms</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="init_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="medi_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="medi_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="medi">
- <property name="label" translatable="yes">Medial Forms</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="medi_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="fina_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="fina_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="fina">
- <property name="label" translatable="yes">Final Forms</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="fina_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="isol_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="isol_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="isol">
- <property name="label" translatable="yes">Isolated Forms</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="isol_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Positional Alternatives</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkExpander">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="margin_start">10</property>
- <property name="margin_end">10</property>
- <property name="margin_top">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="ss01_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss01_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss01">
- <property name="label" translatable="yes">Set 1</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="ss01_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="ss02_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss02_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss02">
- <property name="label" translatable="yes">Set 2</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="ss02_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="ss03_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss03_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss03">
- <property name="label" translatable="yes">Set 3</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="ss03_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="ss04_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss04_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss04">
- <property name="label" translatable="yes">Set 4</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="ss04_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <child>
- <object class="GtkImage" id="ss05_pres">
- <property name="visible">1</property>
- <property name="icon-name">object-select-symbolic</property>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss05_dflt">
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkCheckButton" id="ss05">
- <property name="label" translatable="yes">Set 5</property>
- <property name="visible">1</property>
- <property name="can_focus">1</property>
- <property name="draw_indicator">1</property>
- <property name="valign">baseline</property>
- <signal name="notify::active" handler="update_display" swapped="no"/>
- <property name="sensitive" bind-source="ss05_dflt" bind-property="active" bind-flags="sync-create|bidirectional"/>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Alternative Stylistic Sets</property>
+ <property name="column-spacing">10</property>
+ <property name="row-spacing">10</property>
</object>
</child>
</object>
@@ -1550,13 +120,13 @@
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
+ <property name="hexpand">1</property>
+ <property name="vexpand">1</property>
+ <property name="margin">20</property>
+ <property name="spacing">20</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">1</property>
- <property name="margin_start">20</property>
- <property name="margin_end">20</property>
- <property name="margin_top">20</property>
- <property name="margin_bottom">20</property>
<child>
<object class="GtkLabel" id="label">
<property name="visible">1</property>
@@ -1564,7 +134,7 @@
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="valign">start</property>
- <signal name="button-press-event" handler="switch_to_entry"/>
+ <property name="selectable">1</property>
</object>
<packing>
<property name="name">label</property>
@@ -1579,7 +149,7 @@
Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός</property>
<signal name="key-press-event" handler="entry_key_press"/>
- <signal name="activate" handler="switch_to_label"/>
+ <signal name="activate" handler="stop_edit"/>
<property name="valign">start</property>
<property name="width-chars">50</property>
</object>
@@ -1592,19 +162,46 @@
<child>
<object class="GtkLabel" id="settings">
<property name="visible">1</property>
- <property name="margin_start">20</property>
- <property name="margin_end">20</property>
- <property name="margin_bottom">20</property>
+ <property name="wrap">1</property>
<property name="xalign">0</property>
<property name="valign">end</property>
<property name="width-chars">50</property>
<property name="max-width-chars">50</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
+ <style>
+ <class name="monospace"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="description">
+ <property name="visible">1</property>
+ <property name="wrap">1</property>
+ <property name="xalign">0</property>
+ <property name="valign">end</property>
+ <property name="width-chars">50</property>
+ <property name="max-width-chars">50</property>
+ <property name="hexpand">1</property>
+ <style>
+ <class name="monospace"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="edit_toggle">
+ <property name="icon-name">document-edit-symbolic</property>
+ <property name="halign">end</property>
+ <property name="valign">end</property>
+ <signal name="toggled" handler="toggle_edit"/>
+ </object>
+ </child>
</object>
</child>
- <property name="hexpand">1</property>
- <property name="vexpand">1</property>
</object>
</child>
</object>
diff --git a/demos/gtk-demo/font_features.c b/demos/gtk-demo/font_features.c
index b75508f405..a2df188a6a 100644
--- a/demos/gtk-demo/font_features.c
+++ b/demos/gtk-demo/font_features.c
@@ -1,4 +1,4 @@
-/* Pango/Font Features
+/* Pango/Font Explorer
*
* This example demonstrates support for OpenType font features with
* Pango attributes. The attributes can be used manually or via Pango
@@ -6,6 +6,9 @@
*
* It can also be used to explore available features in OpenType fonts
* and their effect.
+ *
+ * If the selected font supports OpenType font variations, then the
+ * axes are also offered for customization.
*/
#include <gtk/gtk.h>
@@ -13,72 +16,351 @@
#include <hb.h>
#include <hb-ot.h>
#include <hb-ft.h>
+#include <freetype/ftmm.h>
+#include <freetype/ftsnames.h>
+#include <freetype/ttnameid.h>
+#include <glib/gi18n.h>
+
+#include "open-type-layout.h"
+#include "fontplane.h"
+#include "script-names.h"
+#include "language-names.h"
+
+
+#define MAKE_TAG(a,b,c,d) (unsigned int)(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
static GtkWidget *label;
static GtkWidget *settings;
+static GtkWidget *description;
static GtkWidget *font;
static GtkWidget *script_lang;
static GtkWidget *resetbutton;
-static GtkWidget *numcasedefault;
-static GtkWidget *numspacedefault;
-static GtkWidget *fractiondefault;
static GtkWidget *stack;
static GtkWidget *entry;
+static GtkWidget *variations_heading;
+static GtkWidget *variations_grid;
+static GtkWidget *instance_combo;
+static GtkWidget *edit_toggle;
-#define num_features 40
+typedef struct {
+ unsigned int tag;
+ const char *name;
+ GtkWidget *icon;
+ GtkWidget *dflt;
+ GtkWidget *feat;
+} FeatureItem;
-static GtkWidget *toggle[num_features];
-static GtkWidget *icon[num_features];
-static const char *feature_names[num_features] = {
- "kern", "liga", "dlig", "hlig", "clig", "smcp", "c2sc", "pcap", "c2pc", "unic",
- "cpsp", "case", "lnum", "onum", "pnum", "tnum", "frac", "afrc", "zero", "nalt",
- "sinf", "swsh", "cswh", "locl", "calt", "hist", "salt", "titl", "rand", "subs",
- "sups", "init", "medi", "fina", "isol", "ss01", "ss02", "ss03", "ss04", "ss05"
-};
+static GList *feature_items;
+
+typedef struct {
+ unsigned int start;
+ unsigned int end;
+ PangoFontDescription *desc;
+ char *features;
+ PangoLanguage *language;
+} Range;
+
+static GList *ranges;
+
+static void add_font_variations (GString *s);
+
+static void
+free_range (gpointer data)
+{
+ Range *range = data;
+
+ if (range->desc)
+ pango_font_description_free (range->desc);
+ g_free (range->features);
+ g_free (range);
+}
+
+static int
+compare_range (gconstpointer a, gconstpointer b)
+{
+ const Range *ra = a;
+ const Range *rb = b;
+
+ if (ra->start < rb->start)
+ return -1;
+ else if (ra->start > rb->start)
+ return 1;
+ else if (ra->end < rb->end)
+ return 1;
+ else if (ra->end > rb->end)
+ return -1;
+
+ return 0;
+}
+
+static void
+ensure_range (unsigned int start,
+ unsigned int end,
+ PangoFontDescription *desc,
+ const char *features,
+ PangoLanguage *language)
+{
+ GList *l;
+ Range *range;
+
+ for (l = ranges; l; l = l->next)
+ {
+ Range *r = l->data;
+
+ if (r->start == start && r->end == end)
+ {
+ range = r;
+ goto set;
+ }
+ }
+
+ range = g_new0 (Range, 1);
+ range->start = start;
+ range->end = end;
+
+ ranges = g_list_insert_sorted (ranges, range, compare_range);
+
+set:
+ if (range->desc)
+ pango_font_description_free (range->desc);
+ if (desc)
+ range->desc = pango_font_description_copy (desc);
+ g_free (range->features);
+ range->features = g_strdup (features);
+ range->language = language;
+}
+
+static const char *
+get_feature_display_name (unsigned int tag)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (open_type_layout_features); i++)
+ {
+ if (tag == open_type_layout_features[i].tag)
+ return g_dpgettext2 (NULL, "OpenType layout", open_type_layout_features[i].name);
+ }
+
+ return NULL;
+}
+
+static void update_display (void);
+
+static void
+set_inconsistent (GtkCheckButton *button,
+ gboolean inconsistent)
+{
+ gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (button), inconsistent);
+ gtk_widget_set_opacity (gtk_widget_get_first_child (GTK_WIDGET (button)), inconsistent ? 0.0 : 1.0);
+}
+
+static void
+feat_clicked (GtkWidget *feat,
+ gpointer data)
+{
+ g_signal_handlers_block_by_func (feat, feat_clicked, NULL);
+
+ if (gtk_check_button_get_inconsistent (GTK_CHECK_BUTTON (feat)))
+ {
+ set_inconsistent (GTK_CHECK_BUTTON (feat), FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (feat), TRUE);
+ }
+ else if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (feat)))
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (feat), FALSE);
+ }
+ else
+ {
+ set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
+ }
+
+ g_signal_handlers_unblock_by_func (feat, feat_clicked, NULL);
+}
+
+static void
+add_check_group (GtkWidget *box,
+ const char *title,
+ const char **tags)
+{
+ GtkWidget *label;
+ GtkWidget *group;
+ PangoAttrList *attrs;
+ int i;
+
+ group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_halign (group, GTK_ALIGN_START);
+
+ label = gtk_label_new (title);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ g_object_set (label, "margin-top", 10, "margin-bottom", 10, NULL);
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
+ pango_attr_list_unref (attrs);
+ gtk_container_add (GTK_CONTAINER (group), label);
+
+ for (i = 0; tags[i]; i++)
+ {
+ unsigned int tag;
+ GtkWidget *feat;
+ FeatureItem *item;
+
+ tag = hb_tag_from_string (tags[i], -1);
+
+ feat = gtk_check_button_new_with_label (get_feature_display_name (tag));
+ set_inconsistent (GTK_CHECK_BUTTON (feat), TRUE);
+
+ g_signal_connect (feat, "notify::active", G_CALLBACK (update_display), NULL);
+ g_signal_connect (feat, "notify::inconsistent", G_CALLBACK (update_display), NULL);
+ g_signal_connect (feat, "clicked", G_CALLBACK (feat_clicked), NULL);
+
+ gtk_container_add (GTK_CONTAINER (group), feat);
+
+ item = g_new (FeatureItem, 1);
+ item->name = tags[i];
+ item->tag = tag;
+ item->icon = NULL;
+ item->dflt = NULL;
+ item->feat = feat;
+
+ feature_items = g_list_prepend (feature_items, item);
+ }
+
+ gtk_container_add (GTK_CONTAINER (box), group);
+}
+
+static void
+add_radio_group (GtkWidget *box,
+ const char *title,
+ const char **tags)
+{
+ GtkWidget *label;
+ GtkWidget *group;
+ int i;
+ GtkWidget *group_button = NULL;
+ PangoAttrList *attrs;
+
+ group = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_halign (group, GTK_ALIGN_START);
+
+ label = gtk_label_new (title);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ g_object_set (label, "margin-top", 10, "margin-bottom", 10, NULL);
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
+ pango_attr_list_unref (attrs);
+ gtk_container_add (GTK_CONTAINER (group), label);
+
+ for (i = 0; tags[i]; i++)
+ {
+ unsigned int tag;
+ GtkWidget *feat;
+ FeatureItem *item;
+ const char *name;
+
+ tag = hb_tag_from_string (tags[i], -1);
+ name = get_feature_display_name (tag);
+
+ feat = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (group_button),
+ name ? name : _("Default"));
+ if (group_button == NULL)
+ group_button = feat;
+
+ g_signal_connect (feat, "notify::active", G_CALLBACK (update_display), NULL);
+ g_object_set_data (G_OBJECT (feat), "default", group_button);
+
+ gtk_container_add (GTK_CONTAINER (group), feat);
+
+ item = g_new (FeatureItem, 1);
+ item->name = tags[i];
+ item->tag = tag;
+ item->icon = NULL;
+ item->dflt = NULL;
+ item->feat = feat;
+
+ feature_items = g_list_prepend (feature_items, item);
+ }
+
+ gtk_container_add (GTK_CONTAINER (box), group);
+}
static void
update_display (void)
{
GString *s;
- char *font_desc;
- char *font_settings;
const char *text;
gboolean has_feature;
- int i;
- hb_tag_t lang_tag;
- GtkTreeModel *model;
GtkTreeIter iter;
- const char *lang;
+ GtkTreeModel *model;
+ PangoFontDescription *desc;
+ GList *l;
+ PangoAttrList *attrs;
+ PangoAttribute *attr;
+ gint ins, bound;
+ guint start, end;
+ PangoLanguage *lang;
+ char *font_desc;
+ char *features;
text = gtk_entry_get_text (GTK_ENTRY (entry));
- font_desc = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (font));
+ if (gtk_label_get_selection_bounds (GTK_LABEL (label), &ins, &bound))
+ {
+ start = g_utf8_offset_to_pointer (text, ins) - text;
+ end = g_utf8_offset_to_pointer (text, bound) - text;
+ }
+ else
+ {
+ start = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING;
+ end = PANGO_ATTR_INDEX_TO_TEXT_END;
+ }
+
+ desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font));
+
+ s = g_string_new ("");
+ add_font_variations (s);
+ if (s->len > 0)
+ {
+ pango_font_description_set_variations (desc, s->str);
+ g_string_free (s, TRUE);
+ }
+
+ font_desc = pango_font_description_to_string (desc);
s = g_string_new ("");
has_feature = FALSE;
- for (i = 0; i < num_features; i++)
+ for (l = feature_items; l; l = l->next)
{
- if (!gtk_widget_is_sensitive (toggle[i]))
+ FeatureItem *item = l->data;
+
+ if (!gtk_widget_is_sensitive (item->feat))
continue;
- if (GTK_IS_RADIO_BUTTON (toggle[i]))
+ if (GTK_IS_RADIO_BUTTON (item->feat))
{
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle[i])))
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item->feat)) &&
+ strcmp (item->name, "xxxx") != 0)
{
if (has_feature)
g_string_append (s, ", ");
- g_string_append (s, gtk_buildable_get_name (GTK_BUILDABLE (toggle[i])));
+ g_string_append (s, item->name);
g_string_append (s, " 1");
has_feature = TRUE;
}
}
- else
+ else if (GTK_IS_CHECK_BUTTON (item->feat))
{
+ if (gtk_check_button_get_inconsistent (GTK_CHECK_BUTTON (item->feat)))
+ continue;
+
if (has_feature)
g_string_append (s, ", ");
- g_string_append (s, gtk_buildable_get_name (GTK_BUILDABLE (toggle[i])));
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle[i])))
+ g_string_append (s, item->name);
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item->feat)))
g_string_append (s, " 1");
else
g_string_append (s, " 0");
@@ -86,35 +368,58 @@ update_display (void)
}
}
- font_settings = g_string_free (s, FALSE);
-
- gtk_label_set_text (GTK_LABEL (settings), font_settings);
-
+ features = g_string_free (s, FALSE);
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (script_lang), &iter))
{
+ hb_tag_t lang_tag;
+
model = gtk_combo_box_get_model (GTK_COMBO_BOX (script_lang));
gtk_tree_model_get (model, &iter,
3, &lang_tag,
-1);
- lang = hb_language_to_string (hb_ot_tag_to_language (lang_tag));
+ lang = pango_language_from_string (hb_language_to_string (hb_ot_tag_to_language (lang_tag)));
}
else
lang = NULL;
- s = g_string_new ("");
- g_string_append_printf (s, "<span font_desc='%s' font_features='%s'", font_desc, font_settings);
- if (lang)
- g_string_append_printf (s, " lang='%s'", lang);
- g_string_append_printf (s, ">%s</span>", text);
+ ensure_range (start, end, desc, features, lang);
+
+ attrs = pango_attr_list_new ();
- gtk_label_set_markup (GTK_LABEL (label), s->str);
+ for (l = ranges; l; l = l->next)
+ {
+ Range *range = l->data;
+
+ attr = pango_attr_font_desc_new (range->desc);
+ attr->start_index = range->start;
+ attr->end_index = range->end;
+ pango_attr_list_insert (attrs, attr);
- g_string_free (s, TRUE);
+ attr = pango_attr_font_features_new (range->features);
+ attr->start_index = range->start;
+ attr->end_index = range->end;
+ pango_attr_list_insert (attrs, attr);
+
+ if (range->language)
+ {
+ attr = pango_attr_language_new (range->language);
+ attr->start_index = range->start;
+ attr->end_index = range->end;
+ pango_attr_list_insert (attrs, attr);
+ }
+ }
+
+ gtk_label_set_text (GTK_LABEL (description), font_desc);
+ gtk_label_set_text (GTK_LABEL (settings), features);
+ gtk_label_set_text (GTK_LABEL (label), text);
+ gtk_label_set_attributes (GTK_LABEL (label), attrs);
g_free (font_desc);
- g_free (font_settings);
+ pango_font_description_free (desc);
+ g_free (features);
+ pango_attr_list_unref (attrs);
}
static PangoFont *
@@ -122,60 +427,12 @@ get_pango_font (void)
{
PangoFontDescription *desc;
PangoContext *context;
- PangoFontMap *map;
desc = gtk_font_chooser_get_font_desc (GTK_FONT_CHOOSER (font));
context = gtk_widget_get_pango_context (font);
- map = pango_context_get_font_map (context);
-
- return pango_font_map_load_font (map, context, desc);
-}
-
-static struct { const char *name; hb_script_t script; } script_names[] = {
- { "Common", HB_SCRIPT_COMMON },
- { "Inherited", HB_SCRIPT_INHERITED },
- { "Unknown", HB_SCRIPT_UNKNOWN },
- { "Arabic", HB_SCRIPT_ARABIC },
- { "Armenian", HB_SCRIPT_ARMENIAN },
- { "Bengali", HB_SCRIPT_BENGALI },
- { "Cyrillic", HB_SCRIPT_CYRILLIC },
- { "Devanagari", HB_SCRIPT_DEVANAGARI },
- { "Georgian", HB_SCRIPT_GEORGIAN },
- { "Greek", HB_SCRIPT_GREEK },
- { "Gujarati", HB_SCRIPT_GUJARATI },
- { "Gurmukhi", HB_SCRIPT_GURMUKHI },
- { "Hangul", HB_SCRIPT_HANGUL },
- { "Han", HB_SCRIPT_HAN },
- { "Hebrew", HB_SCRIPT_HEBREW },
- { "Hiragana", HB_SCRIPT_HIRAGANA },
- { "Kannada", HB_SCRIPT_KANNADA },
- { "Katakana", HB_SCRIPT_KATAKANA },
- { "Lao", HB_SCRIPT_LAO },
- { "Latin", HB_SCRIPT_LATIN },
- { "Malayalam", HB_SCRIPT_MALAYALAM },
- { "Oriya", HB_SCRIPT_ORIYA },
- { "Tamil", HB_SCRIPT_TAMIL },
- { "Telugu", HB_SCRIPT_TELUGU },
- { "Thai", HB_SCRIPT_THAI },
- { "Tibetan", HB_SCRIPT_TIBETAN },
- { "Bopomofo", HB_SCRIPT_BOPOMOFO }
- /* FIXME: complete */
-};
-static struct { const char *name; hb_tag_t tag; } language_names[] = {
- { "Arabic", HB_TAG ('A','R','A',' ') },
- { "Romanian", HB_TAG ('R','O','M',' ') },
- { "Skolt Sami", HB_TAG ('S','K','S',' ') },
- { "Northern Sami", HB_TAG ('N','S','M',' ') },
- { "Kildin Sami", HB_TAG ('K','S','M',' ') },
- { "Moldavian", HB_TAG ('M','O','L',' ') },
- { "Turkish", HB_TAG ('T','R','K',' ') },
- { "Azerbaijani", HB_TAG ('A','Z','E',' ') },
- { "Crimean Tatar", HB_TAG ('C','R','T',' ') },
- { "Serbian", HB_TAG ('S','R','B',' ') },
- { "German", HB_TAG ('D','E','U',' ') }
- /* FIXME: complete */
-};
+ return pango_context_load_font (context, desc);
+}
typedef struct {
hb_tag_t script_tag;
@@ -201,17 +458,45 @@ tag_pair_equal (gconstpointer a, gconstpointer b)
return pair_a->script_tag == pair_b->script_tag && pair_a->lang_tag == pair_b->lang_tag;
}
+static int
+script_sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ char *sa, *sb;
+ int ret;
+
+ gtk_tree_model_get (model, a, 0, &sa, -1);
+ gtk_tree_model_get (model, b, 0, &sb, -1);
+
+ ret = strcmp (sa, sb);
+
+ g_free (sa);
+ g_free (sb);
+
+ return ret;
+}
+
static void
update_script_combo (void)
{
GtkListStore *store;
hb_font_t *hb_font;
- gint i, j, k, l;
+ gint i, j, k;
FT_Face ft_face;
PangoFont *pango_font;
GHashTable *tags;
GHashTableIter iter;
TagPair *pair;
+ char *lang;
+ hb_tag_t active;
+ GtkTreeIter active_iter;
+ gboolean have_active = FALSE;
+
+ lang = gtk_font_chooser_get_language (GTK_FONT_CHOOSER (font));
+ active = hb_ot_tag_from_language (hb_language_from_string (lang, -1));
+ g_free (lang);
store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
@@ -224,7 +509,7 @@ update_script_combo (void)
pair = g_new (TagPair, 1);
pair->script_tag = HB_OT_TAG_DEFAULT_SCRIPT;
pair->lang_tag = HB_OT_TAG_DEFAULT_LANGUAGE;
- g_hash_table_insert (tags, pair, g_strdup ("Default"));
+ g_hash_table_add (tags, pair);
if (hb_font)
{
@@ -244,13 +529,6 @@ update_script_combo (void)
hb_tag_t languages[80];
unsigned int language_count = G_N_ELEMENTS (languages);
- pair = g_new (TagPair, 1);
- pair->script_tag = scripts[j];
- pair->lang_tag = HB_OT_TAG_DEFAULT_LANGUAGE;
- pair->script_index = j;
- pair->lang_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
- g_hash_table_add (tags, pair);
-
hb_ot_layout_script_get_language_tags (hb_face, tables[i], j, 0, &language_count, languages);
for (k = 0; k < language_count; k++)
{
@@ -273,84 +551,70 @@ update_script_combo (void)
g_hash_table_iter_init (&iter, tags);
while (g_hash_table_iter_next (&iter, (gpointer *)&pair, NULL))
{
- const char *scriptname;
- char scriptbuf[5];
const char *langname;
char langbuf[5];
- char *name;
-
- if (pair->script_tag == HB_OT_TAG_DEFAULT_SCRIPT)
- scriptname = "Default";
- else if (pair->script_tag == HB_TAG ('m','a','t','h'))
- scriptname = "Math";
- else
- {
- hb_script_t script;
-
- hb_tag_to_string (pair->script_tag, scriptbuf);
- scriptbuf[4] = 0;
- scriptname = scriptbuf;
-
- script = hb_script_from_iso15924_tag (pair->script_tag);
- for (k = 0; k < G_N_ELEMENTS (script_names); k++)
- {
- if (script == script_names[k].script)
- {
- scriptname = script_names[k].name;
- break;
- }
- }
- }
+ GtkTreeIter iter;
if (pair->lang_tag == HB_OT_TAG_DEFAULT_LANGUAGE)
- langname = "Default";
+ langname = NC_("Language", "Default");
else
{
- hb_tag_to_string (pair->lang_tag, langbuf);
- langbuf[4] = 0;
- langname = langbuf;
-
- for (l = 0; l < G_N_ELEMENTS (language_names); l++)
+ langname = get_language_name_for_tag (pair->lang_tag);
+ if (!langname)
{
- if (pair->lang_tag == language_names[l].tag)
- {
- langname = language_names[l].name;
- break;
- }
+ hb_tag_to_string (pair->lang_tag, langbuf);
+ langbuf[4] = 0;
+ langname = langbuf;
}
}
- name = g_strdup_printf ("%s - %s", scriptname, langname);
-
- gtk_list_store_insert_with_values (store, NULL, -1,
- 0, name,
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ 0, langname,
1, pair->script_index,
2, pair->lang_index,
3, pair->lang_tag,
-1);
-
- g_free (name);
+ if (pair->lang_tag == active)
+ {
+ have_active = TRUE;
+ active_iter = iter;
+ }
}
g_hash_table_destroy (tags);
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
+ script_sort_func, NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+ GTK_SORT_ASCENDING);
gtk_combo_box_set_model (GTK_COMBO_BOX (script_lang), GTK_TREE_MODEL (store));
- gtk_combo_box_set_active (GTK_COMBO_BOX (script_lang), 0);
+ if (have_active)
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (script_lang), &active_iter);
+ else
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (script_lang), 0);
}
static void
update_features (void)
{
- gint i, j, k;
+ gint i, j;
GtkTreeModel *model;
GtkTreeIter iter;
guint script_index, lang_index;
PangoFont *pango_font;
FT_Face ft_face;
hb_font_t *hb_font;
+ GList *l;
- for (i = 0; i < num_features; i++)
- gtk_widget_set_opacity (icon[i], 0);
+ for (l = feature_items; l; l = l->next)
+ {
+ FeatureItem *item = l->data;
+ gtk_widget_hide (item->feat);
+ gtk_widget_hide (gtk_widget_get_parent (item->feat));
+ if (strcmp (item->name, "xxxx") == 0)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), TRUE);
+ }
/* set feature presence checks from the font features */
@@ -371,6 +635,7 @@ update_features (void)
{
hb_tag_t tables[2] = { HB_OT_TAG_GSUB, HB_OT_TAG_GPOS };
hb_face_t *hb_face;
+ char *feat;
hb_face = hb_font_get_face (hb_font);
@@ -389,14 +654,64 @@ update_features (void)
for (j = 0; j < count; j++)
{
- for (k = 0; k < num_features; k++)
+#if 0
+ char buf[5];
+ hb_tag_to_string (features[j], buf);
+ buf[4] = 0;
+ g_print ("%s present in %s\n", buf, i == 0 ? "GSUB" : "GPOS");
+#endif
+ for (l = feature_items; l; l = l->next)
{
- if (hb_tag_from_string (feature_names[k], -1) == features[j])
- gtk_widget_set_opacity (icon[k], 0.5);
+ FeatureItem *item = l->data;
+
+ if (item->tag == features[j])
+ {
+ gtk_widget_show (item->feat);
+ gtk_widget_show (gtk_widget_get_parent (item->feat));
+ if (GTK_IS_RADIO_BUTTON (item->feat))
+ {
+ GtkWidget *def = GTK_WIDGET (g_object_get_data (G_OBJECT (item->feat), "default"));
+ gtk_widget_show (def);
+ }
+ else if (GTK_IS_CHECK_BUTTON (item->feat))
+ {
+ set_inconsistent (GTK_CHECK_BUTTON (item->feat), TRUE);
+ }
+ }
}
}
}
+ feat = gtk_font_chooser_get_font_features (GTK_FONT_CHOOSER (font));
+ if (feat)
+ {
+ for (l = feature_items; l; l = l->next)
+ {
+ FeatureItem *item = l->data;
+ char buf[5];
+ char *p;
+
+ hb_tag_to_string (item->tag, buf);
+ buf[4] = 0;
+
+ p = strstr (feat, buf);
+ if (p)
+ {
+ if (GTK_IS_RADIO_BUTTON (item->feat))
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), p[6] == '1');
+ }
+ else if (GTK_IS_CHECK_BUTTON (item->feat))
+ {
+ set_inconsistent (GTK_CHECK_BUTTON (item->feat), FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), p[6] == '1');
+ }
+ }
+ }
+
+ g_free (feat);
+ }
+
hb_face_destroy (hb_face);
}
@@ -404,10 +719,885 @@ update_features (void)
g_object_unref (pango_font);
}
+#define FixedToFloat(f) (((float)(f))/65536.0)
+
+static void
+adjustment_changed (GtkAdjustment *adjustment,
+ GtkEntry *entry)
+{
+ char *str;
+
+ str = g_strdup_printf ("%g", gtk_adjustment_get_value (adjustment));
+ gtk_entry_set_text (GTK_ENTRY (entry), str);
+ g_free (str);
+
+ update_display ();
+}
+
+static void
+entry_activated (GtkEntry *entry,
+ GtkAdjustment *adjustment)
+{
+ gdouble value;
+ gchar *err = NULL;
+
+ value = g_strtod (gtk_entry_get_text (entry), &err);
+ if (err != NULL)
+ gtk_adjustment_set_value (adjustment, value);
+}
+
+static void unset_instance (GtkAdjustment *adjustment);
+
+typedef struct {
+ guint32 tag;
+ GtkAdjustment *adjustment;
+} Axis;
+
+static GHashTable *axes;
+
+static void
+add_font_variations (GString *s)
+{
+ GHashTableIter iter;
+ Axis *axis;
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+ char *sep = "";
+
+ g_hash_table_iter_init (&iter, axes);
+ while (g_hash_table_iter_next (&iter, (gpointer *)NULL, (gpointer *)&axis))
+ {
+ char tag[5];
+ double value;
+
+ hb_tag_to_string (axis->tag, tag);
+ tag[4] = '\0';
+ value = gtk_adjustment_get_value (axis->adjustment);
+
+ g_string_append_printf (s, "%s%s=%s", sep, tag, g_ascii_dtostr (buf, sizeof (buf), value));
+ sep = ",";
+ }
+}
+
+static guint
+axes_hash (gconstpointer v)
+{
+ const Axis *p = v;
+
+ return p->tag;
+}
+
+static gboolean
+axes_equal (gconstpointer v1, gconstpointer v2)
+{
+ const Axis *p1 = v1;
+ const Axis *p2 = v2;
+
+ return p1->tag == p2->tag;
+}
+
+static void
+add_axis (FT_Var_Axis *ax, FT_Fixed value, int i)
+{
+ GtkWidget *axis_label;
+ GtkWidget *axis_entry;
+ GtkWidget *axis_scale;
+ GtkAdjustment *adjustment;
+ Axis *axis;
+
+ axis_label = gtk_label_new (ax->name);
+ gtk_widget_set_halign (axis_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (axis_label, GTK_ALIGN_BASELINE);
+ gtk_grid_attach (GTK_GRID (variations_grid), axis_label, 0, i, 1, 1);
+ adjustment = gtk_adjustment_new ((double)FixedToFloat(value),
+ (double)FixedToFloat(ax->minimum),
+ (double)FixedToFloat(ax->maximum),
+ 1.0, 10.0, 0.0);
+ axis_scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adjustment);
+ gtk_scale_add_mark (GTK_SCALE (axis_scale), (double)FixedToFloat(ax->def), GTK_POS_TOP, NULL);
+ gtk_widget_set_valign (axis_scale, GTK_ALIGN_BASELINE);
+ gtk_widget_set_hexpand (axis_scale, TRUE);
+ gtk_widget_set_size_request (axis_scale, 100, -1);
+ gtk_scale_set_draw_value (GTK_SCALE (axis_scale), FALSE);
+ gtk_grid_attach (GTK_GRID (variations_grid), axis_scale, 1, i, 1, 1);
+ axis_entry = gtk_entry_new ();
+ gtk_widget_set_valign (axis_entry, GTK_ALIGN_BASELINE);
+ gtk_entry_set_width_chars (GTK_ENTRY (axis_entry), 4);
+ gtk_grid_attach (GTK_GRID (variations_grid), axis_entry, 2, i, 1, 1);
+
+ axis = g_new (Axis, 1);
+ axis->tag = ax->tag;
+ axis->adjustment = adjustment;
+ g_hash_table_add (axes, axis);
+
+ adjustment_changed (adjustment, GTK_ENTRY (axis_entry));
+
+ g_signal_connect (adjustment, "value-changed", G_CALLBACK (adjustment_changed), axis_entry);
+ g_signal_connect (adjustment, "value-changed", G_CALLBACK (unset_instance), NULL);
+ g_signal_connect (axis_entry, "activate", G_CALLBACK (entry_activated), adjustment);
+}
+
+typedef struct {
+ char *name;
+ int n_axes;
+ guint32 *axes;
+ float *coords;
+} Instance;
+
+static guint
+instance_hash (gconstpointer v)
+{
+ const Instance *p = v;
+
+ return g_str_hash (p->name);
+}
+
+static gboolean
+instance_equal (gconstpointer v1, gconstpointer v2)
+{
+ const Instance *p1 = v1;
+ const Instance *p2 = v2;
+
+ return g_str_equal (p1->name, p2->name);
+}
+
+static void
+free_instance (gpointer data)
+{
+ Instance *instance = data;
+
+ g_free (instance->name);
+ g_free (instance->axes);
+ g_free (instance->coords);
+ g_free (instance);
+}
+
+static GHashTable *instances;
+
+typedef struct {
+ const FT_UShort platform_id;
+ const FT_UShort encoding_id;
+ const char fromcode[12];
+} FtEncoding;
+
+#define TT_ENCODING_DONT_CARE 0xffff
+
+static const FtEncoding ftEncoding[] = {
+ { TT_PLATFORM_APPLE_UNICODE, TT_ENCODING_DONT_CARE, "UTF-16BE" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, "MACINTOSH" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_JAPANESE, "SJIS" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, "UTF-16BE" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, "UTF-16BE" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, "SJIS-WIN" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, "GB2312" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, "BIG-5" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, "Wansung" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, "Johab" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, "UTF-16BE" },
+ { TT_PLATFORM_ISO, TT_ISO_ID_7BIT_ASCII, "ASCII" },
+ { TT_PLATFORM_ISO, TT_ISO_ID_10646, "UTF-16BE" },
+ { TT_PLATFORM_ISO, TT_ISO_ID_8859_1, "ISO-8859-1" },
+};
+
+typedef struct {
+ const FT_UShort platform_id;
+ const FT_UShort language_id;
+ const char lang[8];
+} FtLanguage;
+
+#define TT_LANGUAGE_DONT_CARE 0xffff
+
+static const FtLanguage ftLanguage[] = {
+ { TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE, "" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ENGLISH, "en" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FRENCH, "fr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GERMAN, "de" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ITALIAN, "it" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DUTCH, "nl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWEDISH, "sv" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SPANISH, "es" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DANISH, "da" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PORTUGUESE, "pt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NORWEGIAN, "no" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HEBREW, "he" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAPANESE, "ja" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARABIC, "ar" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FINNISH, "fi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK, "el" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ICELANDIC, "is" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALTESE, "mt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKISH, "tr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CROATIAN, "hr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_TRADITIONAL, "zh-tw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_URDU, "ur" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HINDI, "hi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_THAI, "th" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KOREAN, "ko" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LITHUANIAN, "lt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_POLISH, "pl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HUNGARIAN, "hu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESTONIAN, "et" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LETTISH, "lv" },
+/* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FAEROESE, "fo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FARSI, "fa" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUSSIAN, "ru" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_SIMPLIFIED, "zh-cn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FLEMISH, "nl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH, "ga" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ALBANIAN, "sq" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ROMANIAN, "ro" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CZECH, "cs" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVAK, "sk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVENIAN, "sl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_YIDDISH, "yi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SERBIAN, "sr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MACEDONIAN, "mk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BULGARIAN, "bg" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UKRAINIAN, "uk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BYELORUSSIAN, "be" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UZBEK, "uz" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KAZAKH, "kk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI, "az" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT, "az" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT, "ar" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARMENIAN, "hy" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GEORGIAN, "ka" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MOLDAVIAN, "mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KIRGHIZ, "ky" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAJIKI, "tg" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKMEN, "tk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN, "mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT,"mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT, "mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PASHTO, "ps" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KURDISH, "ku" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KASHMIRI, "ks" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINDHI, "sd" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIBETAN, "bo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NEPALI, "ne" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SANSKRIT, "sa" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MARATHI, "mr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BENGALI, "bn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ASSAMESE, "as" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUJARATI, "gu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PUNJABI, "pa" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ORIYA, "or" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAYALAM, "ml" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KANNADA, "kn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAMIL, "ta" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TELUGU, "te" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINHALESE, "si" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BURMESE, "my" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KHMER, "km" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LAO, "lo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_VIETNAMESE, "vi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INDONESIAN, "id" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAGALOG, "tl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT, "ms" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT, "ms" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AMHARIC, "am" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIGRINYA, "ti" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALLA, "om" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SOMALI, "so" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWAHILI, "sw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUANDA, "rw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUNDI, "rn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHEWA, "ny" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAGASY, "mg" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESPERANTO, "eo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_WELSH, "cy" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BASQUE, "eu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CATALAN, "ca" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LATIN, "la" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_QUECHUA, "qu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUARANI, "gn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AYMARA, "ay" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TATAR, "tt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UIGHUR, "ug" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DZONGKHA, "dz" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAVANESE, "jw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SUNDANESE, "su" },
+
+#if 0 /* these seem to be errors that have been dropped */
+
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC },
+
+#endif
+
+ /* The following codes are new as of 2000-03-10 */
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALICIAN, "gl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AFRIKAANS, "af" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BRETON, "br" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INUKTITUT, "iu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC, "gd" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MANX_GAELIC, "gv" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC, "ga" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TONGAN, "to" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK_POLYTONIC, "el" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREELANDIC, "ik" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT,"az" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SAUDI_ARABIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_IRAQ, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_EGYPT, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LIBYA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_ALGERIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_MOROCCO, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_TUNISIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_OMAN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_YEMEN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SYRIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_JORDAN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LEBANON, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_KUWAIT, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_UAE, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_BAHRAIN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_QATAR, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BULGARIAN_BULGARIA, "bg" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CATALAN_SPAIN, "ca" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_TAIWAN, "zh-tw" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_PRC, "zh-cn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_HONG_KONG, "zh-hk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_SINGAPORE, "zh-sg" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_MACAU, "zh-mo" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CZECH_CZECH_REPUBLIC, "cs" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DANISH_DENMARK, "da" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_GERMANY, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_SWITZERLAND, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_AUSTRIA, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LUXEMBOURG, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LIECHTENSTEI, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE, "el" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_STATES, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_AUSTRALIA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CANADA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_NEW_ZEALAND, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_IRELAND, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_JAMAICA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CARIBBEAN, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_BELIZE, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_TRINIDAD, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_ZIMBABWE, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_PHILIPPINES, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT,"es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_MEXICO, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT,"es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_GUATEMALA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COSTA_RICA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PANAMA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC,"es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_VENEZUELA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COLOMBIA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PERU, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ARGENTINA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ECUADOR, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_CHILE, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_URUGUAY, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PARAGUAY, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_BOLIVIA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_EL_SALVADOR, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_HONDURAS, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_NICARAGUA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PUERTO_RICO, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FINNISH_FINLAND, "fi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_FRANCE, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_BELGIUM, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CANADA, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SWITZERLAND, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_LUXEMBOURG, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MONACO, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HEBREW_ISRAEL, "he" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HUNGARIAN_HUNGARY, "hu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ICELANDIC_ICELAND, "is" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_ITALY, "it" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_SWITZERLAND, "it" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_JAPANESE_JAPAN, "ja" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA,"ko" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_JOHAB_KOREA, "ko" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_NETHERLANDS, "nl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_BELGIUM, "nl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL, "no" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK, "nn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_POLISH_POLAND, "pl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_BRAZIL, "pt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_PORTUGAL, "pt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND,"rm" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ROMANIAN_ROMANIA, "ro" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA, "mo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_RUSSIA, "ru" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_MOLDAVIA, "ru" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CROATIAN_CROATIA, "hr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_LATIN, "sr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC, "sr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVAK_SLOVAKIA, "sk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ALBANIAN_ALBANIA, "sq" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_SWEDEN, "sv" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_FINLAND, "sv" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_THAI_THAILAND, "th" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKISH_TURKEY, "tr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_PAKISTAN, "ur" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INDONESIAN_INDONESIA, "id" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UKRAINIAN_UKRAINE, "uk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BELARUSIAN_BELARUS, "be" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVENE_SLOVENIA, "sl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ESTONIAN_ESTONIA, "et" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATVIAN_LATVIA, "lv" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LITHUANIAN_LITHUANIA, "lt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA,"lt" },
+
+#ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
+ /* this seems to be an error that have been dropped */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MAORI_NEW_ZEALAND, "mi" },
+#endif
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FARSI_IRAN, "fa" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VIETNAMESE_VIET_NAM, "vi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARMENIAN_ARMENIA, "hy" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN, "az" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC, "az" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BASQUE_SPAIN, "eu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SORBIAN_GERMANY, "wen" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MACEDONIAN_MACEDONIA, "mk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SUTU_SOUTH_AFRICA, "st" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSONGA_SOUTH_AFRICA, "ts" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSWANA_SOUTH_AFRICA, "tn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VENDA_SOUTH_AFRICA, "ven" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_XHOSA_SOUTH_AFRICA, "xh" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ZULU_SOUTH_AFRICA, "zu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA, "af" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GEORGIAN_GEORGIA, "ka" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS, "fo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HINDI_INDIA, "hi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALTESE_MALTA, "mt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SAAMI_LAPONIA, "se" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM,"gd" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IRISH_GAELIC_IRELAND, "ga" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_MALAYSIA, "ms" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM, "ms" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KAZAK_KAZAKSTAN, "kk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWAHILI_KENYA, "sw" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN, "uz" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC, "uz" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TATAR_TATARSTAN, "tt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_INDIA, "bn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_INDIA, "pa" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUJARATI_INDIA, "gu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ORIYA_INDIA, "or" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMIL_INDIA, "ta" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TELUGU_INDIA, "te" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANNADA_INDIA, "kn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAYALAM_INDIA, "ml" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ASSAMESE_INDIA, "as" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MARATHI_INDIA, "mr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SANSKRIT_INDIA, "sa" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KONKANI_INDIA, "kok" },
+
+ /* new as of 2001-01-01 */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_GENERAL, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_GENERAL, "zh" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_GENERAL, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_WEST_INDIES, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_REUNION, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CONGO, "fr" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SENEGAL, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CAMEROON, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MALI, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA,"bs" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_INDIA, "ur" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAJIK_TAJIKISTAN, "tg" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YIDDISH_GERMANY, "yi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN, "ky" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKMEN_TURKMENISTAN, "tk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA, "mn" },
+
+ /* the following seems to be inconsistent;
+ here is the current "official" way: */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_BHUTAN, "bo" },
+ /* and here is what is used by Passport SDK */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_CHINA, "bo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DZONGHKA_BHUTAN, "dz" },
+ /* end of inconsistency */
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_WELSH_WALES, "cy" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KHMER_CAMBODIA, "km" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LAO_LAOS, "lo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BURMESE_MYANMAR, "my" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GALICIAN_SPAIN, "gl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MANIPURI_INDIA, "mni" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINDHI_INDIA, "sd" },
+ /* the following one is only encountered in Microsoft RTF specification */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_PAKISTAN, "ks" },
+ /* the following one is not in the Passport list, looks like an omission */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_INDIA, "ks" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_NEPAL, "ne" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_INDIA, "ne" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRISIAN_NETHERLANDS, "fy" },
+
+ /* new as of 2001-03-01 (from Office Xp) */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_HONG_KONG, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_INDIA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_MALAYSIA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SINGAPORE, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SYRIAC_SYRIA, "syr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINHALESE_SRI_LANKA, "si" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHEROKEE_UNITED_STATES, "chr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INUKTITUT_CANADA, "iu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AMHARIC_ETHIOPIA, "am" },
+#if 0
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN },
+#endif
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PASHTO_AFGHANISTAN, "ps" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FILIPINO_PHILIPPINES, "phi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DHIVEHI_MALDIVES, "div" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_OROMO_ETHIOPIA, "om" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ETHIOPIA, "ti" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ERYTHREA, "ti" },
+
+ /* New additions from Windows Xp/Passport SDK 2001-11-10. */
+
+ /* don't ask what this one means... It is commented out currently. */
+#if 0
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE2 },
+#endif
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_UNITED_STATES, "es" },
+ /* The following two IDs blatantly violate MS specs by using a */
+ /* sublanguage >,. */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_LATIN_AMERICA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_NORTH_AFRICA, "fr" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MOROCCO, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_HAITI, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_BANGLADESH, "bn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN,"mn" },
+#if 0
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_EDO_NIGERIA },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FULFULDE_NIGERIA },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IBIBIO_NIGERIA },
+#endif
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAUSA_NIGERIA, "ha" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YORUBA_NIGERIA, "yo" },
+ /* language codes from, to, are (still) unknown. */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IGBO_NIGERIA, "ibo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANURI_NIGERIA, "kau" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUARANI_PARAGUAY, "gn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAWAIIAN_UNITED_STATES, "haw" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATIN, "la" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SOMALI_SOMALIA, "so" },
+#if 0
+ /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
+ /* not written (but OTOH the peculiar writing system is worth */
+ /* studying). */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YI_CHINA },
+#endif
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" },
+};
+
+static const char *
+FcSfntNameLanguage (FT_SfntName *sname)
+{
+ int i;
+ FT_UShort platform_id = sname->platform_id;
+ FT_UShort language_id = sname->language_id;
+
+ for (i = 0; i < G_N_ELEMENTS (ftLanguage); i++)
+ if (ftLanguage[i].platform_id == platform_id &&
+ (ftLanguage[i].language_id == TT_LANGUAGE_DONT_CARE ||
+ ftLanguage[i].language_id == language_id))
+ {
+ if (ftLanguage[i].lang[0] == '\0')
+ return NULL;
+ else
+ return ftLanguage[i].lang;
+ }
+ return NULL;
+}
+
+static char *
+FcSfntNameTranscode (FT_SfntName *name)
+{
+ int i;
+ const char *fromcode;
+
+ for (i = 0; i < G_N_ELEMENTS (ftEncoding); i++)
+ if (ftEncoding[i].platform_id == name->platform_id &&
+ (ftEncoding[i].encoding_id == TT_ENCODING_DONT_CARE ||
+ ftEncoding[i].encoding_id == name->encoding_id))
+ break;
+ if (i == G_N_ELEMENTS (ftEncoding))
+ return NULL;
+ fromcode = ftEncoding[i].fromcode;
+
+ return g_convert ((const char *)name->string, name->string_len, "UTF-8", fromcode, NULL, NULL, NULL);
+}
+
+static char *
+get_sfnt_name (FT_Face ft_face,
+ guint nameid)
+{
+ guint count;
+ guint i, j;
+ const char * const *langs = g_get_language_names ();
+ char *res = NULL;
+ guint pos = G_MAXUINT;
+
+ count = FT_Get_Sfnt_Name_Count (ft_face);
+ for (i = 0; i < count; i++)
+ {
+ FT_SfntName name;
+ const char *lang;
+
+ if (FT_Get_Sfnt_Name (ft_face, i, &name) != 0)
+ continue;
+
+ if (name.name_id != nameid)
+ continue;
+
+ lang = FcSfntNameLanguage (&name);
+ for (j = 0; j < pos && langs[j]; j++)
+ {
+ if (strcmp (lang, langs[j]) == 0)
+ {
+ pos = j;
+ g_free (res);
+ res = FcSfntNameTranscode (&name);
+ }
+ }
+
+ if (pos == 0)
+ break;
+ }
+
+ return res;
+}
+
+static gboolean
+is_valid_subfamily_id (guint id)
+{
+ return id == 2 || id == 17 || (255 < id && id < 32768);
+}
+
+static void
+add_instance (FT_Face ft_face,
+ FT_MM_Var *ft_mm_var,
+ FT_Var_Named_Style *ns,
+ GtkWidget *combo,
+ int pos)
+{
+ Instance *instance;
+ int i;
+
+ instance = g_new0 (Instance, 1);
+
+ if (is_valid_subfamily_id (ns->strid))
+ instance->name = get_sfnt_name (ft_face, ns->strid);
+ if (!instance->name)
+ instance->name = g_strdup_printf ("Instance %d", pos);
+
+ g_hash_table_add (instances, instance);
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), instance->name);
+
+ instance->n_axes = ft_mm_var->num_axis;
+ instance->axes = g_new (guint32, ft_mm_var->num_axis);
+ instance->coords = g_new (float, ft_mm_var->num_axis);
+
+ for (i = 0; i < ft_mm_var->num_axis; i++)
+ {
+ instance->axes[i] = ft_mm_var->axis[i].tag;
+ instance->coords[i] = FixedToFloat(ns->coords[i]);
+ }
+}
+
+static void
+unset_instance (GtkAdjustment *adjustment)
+{
+ if (instance_combo)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (instance_combo), 0);
+}
+
+static void
+instance_changed (GtkComboBox *combo)
+{
+ char *text;
+ Instance *instance;
+ Instance ikey;
+ int i;
+
+ text = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
+ if (text[0] == '\0')
+ goto out;
+
+ ikey.name = text;
+ instance = g_hash_table_lookup (instances, &ikey);
+ if (!instance)
+ {
+ g_print ("did not find instance %s\n", text);
+ goto out;
+ }
+
+ for (i = 0; i < instance->n_axes; i++)
+ {
+ Axis *axis;
+ Axis akey;
+ guint32 tag;
+ gdouble value;
+
+ tag = instance->axes[i];
+ value = instance->coords[i];
+
+ akey.tag = tag;
+ axis = g_hash_table_lookup (axes, &akey);
+ if (axis)
+ {
+ g_signal_handlers_block_by_func (axis->adjustment, unset_instance, NULL);
+ gtk_adjustment_set_value (axis->adjustment, value);
+ g_signal_handlers_unblock_by_func (axis->adjustment, unset_instance, NULL);
+ }
+ }
+
+out:
+ g_free (text);
+}
+
+static gboolean
+matches_instance (FT_Var_Named_Style *instance,
+ FT_Fixed *coords,
+ FT_UInt num_coords)
+{
+ FT_UInt i;
+
+ for (i = 0; i < num_coords; i++)
+ if (coords[i] != instance->coords[i])
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+add_font_plane (int i)
+{
+ GtkWidget *plane;
+ Axis *weight_axis;
+ Axis *width_axis;
+
+ Axis key;
+
+ key.tag = MAKE_TAG('w','g','h','t');
+ weight_axis = g_hash_table_lookup (axes, &key);
+ key.tag = MAKE_TAG('w','d','t','h');
+ width_axis = g_hash_table_lookup (axes, &key);
+
+ if (weight_axis && width_axis)
+ {
+ plane = gtk_font_plane_new (weight_axis->adjustment,
+ width_axis->adjustment);
+
+ gtk_widget_set_size_request (plane, 300, 300);
+ gtk_widget_set_halign (plane, GTK_ALIGN_CENTER);
+ gtk_grid_attach (GTK_GRID (variations_grid), plane, 0, i, 3, 1);
+ }
+}
+
+static void
+update_font_variations (void)
+{
+ GtkWidget *child, *next;
+ PangoFont *pango_font;
+ FT_Face ft_face;
+ FT_MM_Var *ft_mm_var;
+ FT_Error ret;
+
+ child = gtk_widget_get_first_child (variations_grid);
+ while (child != NULL)
+ {
+ next = gtk_widget_get_next_sibling (child);
+ gtk_widget_destroy (child);
+ child = next;
+ }
+
+ instance_combo = NULL;
+
+ g_hash_table_remove_all (axes);
+ g_hash_table_remove_all (instances);
+
+ pango_font = get_pango_font ();
+ ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
+
+ ret = FT_Get_MM_Var (ft_face, &ft_mm_var);
+ if (ret == 0)
+ {
+ unsigned int i;
+ FT_Fixed *coords;
+
+ coords = g_new (FT_Fixed, ft_mm_var->num_axis);
+ ret = FT_Get_Var_Design_Coordinates (ft_face, ft_mm_var->num_axis, coords);
+
+ if (ft_mm_var->num_namedstyles > 0)
+ {
+ GtkWidget *label;
+ GtkWidget *combo;
+
+ label = gtk_label_new ("Instance");
+ gtk_label_set_xalign (GTK_LABEL (label), 0);
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+ gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
+ gtk_grid_attach (GTK_GRID (variations_grid), label, 0, -1, 2, 1);
+
+ combo = gtk_combo_box_text_new ();
+ gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE);
+ g_signal_connect (combo, "changed", G_CALLBACK (instance_changed), NULL);
+ gtk_grid_attach (GTK_GRID (variations_grid), combo, 1, -1, 2, 1);
+
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "");
+
+ for (i = 0; i < ft_mm_var->num_namedstyles; i++)
+ add_instance (ft_face, ft_mm_var, &ft_mm_var->namedstyle[i], combo, i);
+ for (i = 0; i < ft_mm_var->num_namedstyles; i++)
+ {
+ if (matches_instance (&ft_mm_var->namedstyle[i], coords, ft_mm_var->num_axis))
+ {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i + 1);
+ break;
+ }
+ }
+
+ instance_combo = combo;
+ }
+
+ if (ret == 0)
+ {
+ for (i = 0; i < ft_mm_var->num_axis; i++)
+ add_axis (&ft_mm_var->axis[i], coords[i], i);
+
+ add_font_plane (ft_mm_var->num_axis);
+ }
+ g_free (coords);
+ free (ft_mm_var);
+ }
+
+ pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+ g_object_unref (pango_font);
+}
+
static void
font_changed (void)
{
update_script_combo ();
+ update_features ();
+ update_font_variations ();
}
static void
@@ -420,17 +1610,26 @@ script_changed (void)
static void
reset_features (void)
{
- int i;
+ GList *l;
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (numcasedefault), TRUE);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (numspacedefault), TRUE);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fractiondefault), TRUE);
- for (i = 0; i < num_features; i++)
+ gtk_label_select_region (GTK_LABEL (label), 0, 0);
+
+ g_list_free_full (ranges, free_range);
+ ranges = NULL;
+
+ for (l = feature_items; l; l = l->next)
{
- if (!GTK_IS_RADIO_BUTTON (toggle[i]))
+ FeatureItem *item = l->data;
+
+ if (GTK_IS_RADIO_BUTTON (item->feat))
{
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle[i]), FALSE);
- gtk_widget_set_sensitive (toggle[i], FALSE);
+ if (strcmp (item->name, "xxxx") == 0)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), TRUE);
+ }
+ else if (GTK_IS_CHECK_BUTTON (item->feat))
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->feat), FALSE);
+ set_inconsistent (GTK_CHECK_BUTTON (item->feat), TRUE);
}
}
}
@@ -442,6 +1641,7 @@ switch_to_entry (void)
{
text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
gtk_stack_set_visible_child_name (GTK_STACK (stack), "entry");
+ gtk_widget_grab_focus (entry);
}
static void
@@ -453,6 +1653,21 @@ switch_to_label (void)
update_display ();
}
+static void
+toggle_edit (void)
+{
+ if (strcmp (gtk_stack_get_visible_child_name (GTK_STACK (stack)), "label") == 0)
+ switch_to_entry ();
+ else
+ switch_to_label ();
+}
+
+static void
+stop_edit (void)
+{
+ gtk_button_clicked (GTK_BUTTON (edit_toggle));
+}
+
static gboolean
entry_key_press (GtkEntry *entry, GdkEventKey *event)
{
@@ -463,7 +1678,7 @@ entry_key_press (GtkEntry *entry, GdkEventKey *event)
if (keyval == GDK_KEY_Escape)
{
gtk_entry_set_text (GTK_ENTRY (entry), text);
- switch_to_label ();
+ stop_edit ();
return GDK_EVENT_STOP;
}
@@ -478,7 +1693,7 @@ do_font_features (GtkWidget *do_widget)
if (!window)
{
GtkBuilder *builder;
- int i;
+ GtkWidget *feature_list;
builder = gtk_builder_new_from_resource ("/font_features/font-features.ui");
@@ -486,32 +1701,121 @@ do_font_features (GtkWidget *do_widget)
gtk_builder_add_callback_symbol (builder, "font_changed", font_changed);
gtk_builder_add_callback_symbol (builder, "script_changed", script_changed);
gtk_builder_add_callback_symbol (builder, "reset", reset_features);
- gtk_builder_add_callback_symbol (builder, "switch_to_entry", switch_to_entry);
- gtk_builder_add_callback_symbol (builder, "switch_to_label", switch_to_label);
+ gtk_builder_add_callback_symbol (builder, "stop_edit", G_CALLBACK (stop_edit));
+ gtk_builder_add_callback_symbol (builder, "toggle_edit", G_CALLBACK (toggle_edit));
gtk_builder_add_callback_symbol (builder, "entry_key_press", G_CALLBACK (entry_key_press));
gtk_builder_connect_signals (builder, NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
+ feature_list = GTK_WIDGET (gtk_builder_get_object (builder, "feature_list"));
label = GTK_WIDGET (gtk_builder_get_object (builder, "label"));
settings = GTK_WIDGET (gtk_builder_get_object (builder, "settings"));
+ description = GTK_WIDGET (gtk_builder_get_object (builder, "description"));
resetbutton = GTK_WIDGET (gtk_builder_get_object (builder, "reset"));
font = GTK_WIDGET (gtk_builder_get_object (builder, "font"));
script_lang = GTK_WIDGET (gtk_builder_get_object (builder, "script_lang"));
- numcasedefault = GTK_WIDGET (gtk_builder_get_object (builder, "numcasedefault"));
- numspacedefault = GTK_WIDGET (gtk_builder_get_object (builder, "numspacedefault"));
- fractiondefault = GTK_WIDGET (gtk_builder_get_object (builder, "fractiondefault"));
stack = GTK_WIDGET (gtk_builder_get_object (builder, "stack"));
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
+ edit_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "edit_toggle"));
+
+ add_check_group (feature_list, _("Kerning"), (const char *[]){ "kern", NULL });
+ add_check_group (feature_list, _("Ligatures"), (const char *[]){ "liga",
+ "dlig",
+ "hlig",
+ "clig",
+ "rlig", NULL });
+ add_check_group (feature_list, _("Letter Case"), (const char *[]){ "smcp",
+ "c2sc",
+ "pcap",
+ "c2pc",
+ "unic",
+ "cpsp",
+ "case",NULL });
+ add_radio_group (feature_list, _("Number Case"), (const char *[]){ "xxxx",
+ "lnum",
+ "onum", NULL });
+ add_radio_group (feature_list, _("Number Spacing"), (const char *[]){ "xxxx",
+ "pnum",
+ "tnum", NULL });
+ add_radio_group (feature_list, _("Fractions"), (const char *[]){ "xxxx",
+ "frac",
+ "afrc", NULL });
+ add_check_group (feature_list, _("Numeric Extras"), (const char *[]){ "zero",
+ "nalt",
+ "sinf", NULL });
+ add_check_group (feature_list, _("Character Alternatives"), (const char *[]){ "swsh",
+ "cswh",
+ "locl",
+ "calt",
+ "falt",
+ "hist",
+ "salt",
+ "jalt",
+ "titl",
+ "rand",
+ "subs",
+ "sups",
+ "ordn",
+ "ltra",
+ "ltrm",
+ "rtla",
+ "rtlm",
+ "rclt", NULL });
+ add_check_group (feature_list, _("Positional Alternatives"), (const char *[]){ "init",
+ "medi",
+ "med2",
+ "fina",
+ "fin2",
+ "fin3",
+ "isol", NULL });
+ add_check_group (feature_list, _("Width Variants"), (const char *[]){ "fwid",
+ "hwid",
+ "halt",
+ "pwid",
+ "palt",
+ "twid",
+ "qwid", NULL });
+ add_check_group (feature_list, _("Alternative Stylistic Sets"), (const char *[]){ "ss00",
+ "ss01",
+ "ss02",
+ "ss03",
+ "ss04",
+ "ss05",
+ "ss06",
+ "ss07",
+ "ss08",
+ "ss09",
+ "ss10",
+ "ss11",
+ "ss12",
+ "ss13",
+ "ss14",
+ "ss15",
+ "ss16",
+ "ss17",
+ "ss18",
+ "ss19",
+ "ss20", NULL });
+ add_check_group (feature_list, _("Mathematical"), (const char *[]){ "dtls",
+ "flac",
+ "mgrk",
+ "ssty", NULL });
+ add_check_group (feature_list, _("Optical Bounds"), (const char *[]){ "opbd",
+ "lfbd",
+ "rtbd", NULL });
+ feature_items = g_list_reverse (feature_items);
+
+ variations_heading = GTK_WIDGET (gtk_builder_get_object (builder, "variations_heading"));
+ variations_grid = GTK_WIDGET (gtk_builder_get_object (builder, "variations_grid"));
+ if (instances == NULL)
+ instances = g_hash_table_new_full (instance_hash, instance_equal, NULL, free_instance);
+ else
+ g_hash_table_remove_all (instances);
- for (i = 0; i < num_features; i++)
- {
- char *iname;
-
- toggle[i] = GTK_WIDGET (gtk_builder_get_object (builder, feature_names[i]));
- iname = g_strconcat (feature_names[i], "_pres", NULL);
- icon[i] = GTK_WIDGET (gtk_builder_get_object (builder, iname));
- g_free (iname);
- }
+ if (axes == NULL)
+ axes = g_hash_table_new_full (axes_hash, axes_equal, NULL, g_free);
+ else
+ g_hash_table_remove_all (axes);
font_changed ();
diff --git a/demos/gtk-demo/fontplane.c b/demos/gtk-demo/fontplane.c
new file mode 100644
index 0000000000..0e7e2d0b7d
--- /dev/null
+++ b/demos/gtk-demo/fontplane.c
@@ -0,0 +1,315 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "fontplane.h"
+
+#include "gtk.h"
+
+enum {
+ PROP_0,
+ PROP_WEIGHT_ADJUSTMENT,
+ PROP_WIDTH_ADJUSTMENT
+};
+
+G_DEFINE_TYPE (GtkFontPlane, gtk_font_plane, GTK_TYPE_WIDGET)
+
+static double
+adjustment_get_normalized_value (GtkAdjustment *adj)
+{
+ return (gtk_adjustment_get_value (adj) - gtk_adjustment_get_lower (adj)) /
+ (gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj));
+}
+
+static void
+val_to_xy (GtkFontPlane *plane,
+ gint *x,
+ gint *y)
+{
+ gdouble u, v;
+ gint width, height;
+
+ width = gtk_widget_get_allocated_width (GTK_WIDGET (plane));
+ height = gtk_widget_get_allocated_height (GTK_WIDGET (plane));
+
+ u = adjustment_get_normalized_value (plane->width_adj);
+ v = adjustment_get_normalized_value (plane->weight_adj);
+
+ *x = CLAMP (width * u, 0, width - 1);
+ *y = CLAMP (height * (1 - v), 0, height - 1);
+}
+
+static void
+plane_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GtkFontPlane *plane = GTK_FONT_PLANE (widget);
+ gint x, y;
+ gint width, height;
+ cairo_t *cr;
+
+ val_to_xy (plane, &x, &y);
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+
+ cr = gtk_snapshot_append_cairo (snapshot,
+ &GRAPHENE_RECT_INIT (0, 0, width, height),
+ "FontPlane");
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_paint (cr);
+
+ cairo_move_to (cr, 0, y + 0.5);
+ cairo_line_to (cr, width, y + 0.5);
+
+ cairo_move_to (cr, x + 0.5, 0);
+ cairo_line_to (cr, x + 0.5, height);
+
+ if (gtk_widget_has_visible_focus (widget))
+ {
+ cairo_set_line_width (cr, 3.0);
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6);
+ cairo_stroke_preserve (cr);
+
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.8);
+ cairo_stroke (cr);
+ }
+ else
+ {
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.8);
+ cairo_stroke (cr);
+ }
+
+ cairo_destroy (cr);
+}
+
+static void
+set_cross_cursor (GtkWidget *widget,
+ gboolean enabled)
+{
+ if (enabled)
+ gtk_widget_set_cursor_from_name (widget, "crosshair");
+ else
+ gtk_widget_set_cursor (widget, NULL);
+}
+
+static void
+adj_changed (GtkFontPlane *plane)
+{
+ gtk_widget_queue_draw (GTK_WIDGET (plane));
+}
+
+static void
+adjustment_set_normalized_value (GtkAdjustment *adj,
+ double val)
+{
+ gtk_adjustment_set_value (adj,
+ gtk_adjustment_get_lower (adj) +
+ val * (gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj)));
+}
+
+static void
+update_value (GtkFontPlane *plane,
+ gint x,
+ gint y)
+{
+ GtkWidget *widget = GTK_WIDGET (plane);
+ gdouble u, v;
+
+ u = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1);
+ v = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1);
+
+ adjustment_set_normalized_value (plane->width_adj, u);
+ adjustment_set_normalized_value (plane->weight_adj, v);
+
+ gtk_widget_queue_draw (widget);
+}
+
+static void
+hold_action (GtkGestureLongPress *gesture,
+ gdouble x,
+ gdouble y,
+ GtkFontPlane *plane)
+{
+ gboolean handled;
+
+ g_signal_emit_by_name (plane, "popup-menu", &handled);
+}
+
+static void
+plane_drag_gesture_begin (GtkGestureDrag *gesture,
+ gdouble start_x,
+ gdouble start_y,
+ GtkFontPlane *plane)
+{
+ guint button;
+
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+
+ if (button == GDK_BUTTON_SECONDARY)
+ {
+ gboolean handled;
+
+ g_signal_emit_by_name (plane, "popup-menu", &handled);
+ }
+
+ if (button != GDK_BUTTON_PRIMARY)
+ {
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ set_cross_cursor (GTK_WIDGET (plane), TRUE);
+ update_value (plane, start_x, start_y);
+ gtk_widget_grab_focus (GTK_WIDGET (plane));
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+}
+
+static void
+plane_drag_gesture_update (GtkGestureDrag *gesture,
+ gdouble offset_x,
+ gdouble offset_y,
+ GtkFontPlane *plane)
+{
+ gdouble start_x, start_y;
+
+ gtk_gesture_drag_get_start_point (GTK_GESTURE_DRAG (gesture),
+ &start_x, &start_y);
+ update_value (plane, start_x + offset_x, start_y + offset_y);
+}
+
+static void
+plane_drag_gesture_end (GtkGestureDrag *gesture,
+ gdouble offset_x,
+ gdouble offset_y,
+ GtkFontPlane *plane)
+{
+ set_cross_cursor (GTK_WIDGET (plane), FALSE);
+}
+
+static void
+gtk_font_plane_init (GtkFontPlane *plane)
+{
+ gtk_widget_set_has_window (GTK_WIDGET (plane), FALSE);
+ gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE);
+
+ plane->drag_gesture = gtk_gesture_drag_new (GTK_WIDGET (plane));
+ g_signal_connect (plane->drag_gesture, "drag-begin",
+ G_CALLBACK (plane_drag_gesture_begin), plane);
+ g_signal_connect (plane->drag_gesture, "drag-update",
+ G_CALLBACK (plane_drag_gesture_update), plane);
+ g_signal_connect (plane->drag_gesture, "drag-end",
+ G_CALLBACK (plane_drag_gesture_end), plane);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (plane->drag_gesture), 0);
+
+ plane->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (plane));
+ g_signal_connect (plane->long_press_gesture, "pressed",
+ G_CALLBACK (hold_action), plane);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (plane->long_press_gesture),
+ TRUE);
+}
+
+static void
+plane_finalize (GObject *object)
+{
+ GtkFontPlane *plane = GTK_FONT_PLANE (object);
+
+ g_clear_object (&plane->weight_adj);
+ g_clear_object (&plane->width_adj);
+
+ g_clear_object (&plane->drag_gesture);
+ g_clear_object (&plane->long_press_gesture);
+
+ G_OBJECT_CLASS (gtk_font_plane_parent_class)->finalize (object);
+}
+
+static void
+plane_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkFontPlane *plane = GTK_FONT_PLANE (object);
+ GtkAdjustment *adjustment;
+
+ switch (prop_id)
+ {
+ case PROP_WEIGHT_ADJUSTMENT:
+ adjustment = GTK_ADJUSTMENT (g_value_get_object (value));
+ if (adjustment)
+ {
+ plane->weight_adj = g_object_ref_sink (adjustment);
+ g_signal_connect_swapped (adjustment, "value-changed", G_CALLBACK (adj_changed), plane);
+ }
+ break;
+ case PROP_WIDTH_ADJUSTMENT:
+ adjustment = GTK_ADJUSTMENT (g_value_get_object (value));
+ if (adjustment)
+ {
+ plane->width_adj = g_object_ref_sink (adjustment);
+ g_signal_connect_swapped (adjustment, "value-changed", G_CALLBACK (adj_changed), plane);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_font_plane_class_init (GtkFontPlaneClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->finalize = plane_finalize;
+ object_class->set_property = plane_set_property;
+
+ widget_class->snapshot = plane_snapshot;
+
+ g_object_class_install_property (object_class,
+ PROP_WEIGHT_ADJUSTMENT,
+ g_param_spec_object ("weight-adjustment",
+ NULL,
+ NULL,
+ GTK_TYPE_ADJUSTMENT,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_WIDTH_ADJUSTMENT,
+ g_param_spec_object ("width-adjustment",
+ NULL,
+ NULL,
+ GTK_TYPE_ADJUSTMENT,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+GtkWidget *
+gtk_font_plane_new (GtkAdjustment *weight_adj,
+ GtkAdjustment *width_adj)
+{
+ return g_object_new (GTK_TYPE_FONT_PLANE,
+ "weight-adjustment", weight_adj,
+ "width-adjustment", width_adj,
+ NULL);
+}
diff --git a/demos/gtk-demo/fontplane.h b/demos/gtk-demo/fontplane.h
new file mode 100644
index 0000000000..e9983a1194
--- /dev/null
+++ b/demos/gtk-demo/fontplane.h
@@ -0,0 +1,65 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_FONT_PLANE_H__
+#define __GTK_FONT_PLANE_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_FONT_PLANE (gtk_font_plane_get_type ())
+#define GTK_FONT_PLANE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FONT_PLANE, GtkFontPlane))
+#define GTK_FONT_PLANE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FONT_PLANE, GtkFontPlaneClass))
+#define GTK_IS_FONT_PLANE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_PLANE))
+#define GTK_IS_FONT_PLANE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_PLANE))
+#define GTK_FONT_PLANE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FONT_PLANE, GtkFontPlaneClass))
+
+
+typedef struct _GtkFontPlane GtkFontPlane;
+typedef struct _GtkFontPlaneClass GtkFontPlaneClass;
+
+struct _GtkFontPlane
+{
+ GtkWidget parent_instance;
+
+ GtkAdjustment *weight_adj;
+ GtkAdjustment *width_adj;
+
+ GtkGesture *drag_gesture;
+ GtkGesture *long_press_gesture;
+};
+
+struct _GtkFontPlaneClass
+{
+ GtkWidgetClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+
+GType gtk_font_plane_get_type (void) G_GNUC_CONST;
+GtkWidget * gtk_font_plane_new (GtkAdjustment *width_adj,
+ GtkAdjustment *weight_adj);
+
+G_END_DECLS
+
+#endif /* __GTK_FONT_PLANE_H__ */
diff --git a/demos/gtk-demo/language-names.c b/demos/gtk-demo/language-names.c
new file mode 100644
index 0000000000..2d433cff06
--- /dev/null
+++ b/demos/gtk-demo/language-names.c
@@ -0,0 +1,233 @@
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <hb-ot.h>
+
+#include "language-names.h"
+
+#define ISO_CODES_PREFIX "/usr"
+#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
+#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
+
+static GHashTable *language_map;
+
+static char *
+get_first_item_in_semicolon_list (const char *list)
+{
+ char **items;
+ char *item;
+
+ items = g_strsplit (list, "; ", 2);
+
+ item = g_strdup (items[0]);
+ g_strfreev (items);
+
+ return item;
+}
+
+static char *
+capitalize_utf8_string (const char *str)
+{
+ char first[8] = { 0 };
+
+ if (!str)
+ return NULL;
+
+ g_unichar_to_utf8 (g_unichar_totitle (g_utf8_get_char (str)), first);
+
+ return g_strconcat (first, g_utf8_offset_to_pointer (str, 1), NULL);
+}
+
+static char *
+get_display_name (const char *language)
+{
+ const char *translated;
+ char *tmp;
+ char *name;
+
+ translated = dgettext ("iso_639", language);
+
+ tmp = get_first_item_in_semicolon_list (translated);
+ name = capitalize_utf8_string (tmp);
+ g_free (tmp);
+
+ return name;
+}
+
+static void
+languages_parse_start_tag (GMarkupParseContext *ctx,
+ const char *element_name,
+ const char **attr_names,
+ const char **attr_values,
+ gpointer user_data,
+ GError **error)
+{
+ const char *ccode_longB;
+ const char *ccode_longT;
+ const char *ccode;
+ const char *ccode_id;
+ const char *lang_name;
+ char *display_name;
+
+ if (!(g_str_equal (element_name, "iso_639_entry") ||
+ g_str_equal (element_name, "iso_639_3_entry")) ||
+ attr_names == NULL ||
+ attr_values == NULL)
+ return;
+
+ ccode = NULL;
+ ccode_longB = NULL;
+ ccode_longT = NULL;
+ ccode_id = NULL;
+ lang_name = NULL;
+
+ while (*attr_names && *attr_values)
+ {
+ if (g_str_equal (*attr_names, "iso_639_1_code"))
+ {
+ if (**attr_values)
+ {
+ if (strlen (*attr_values) != 2)
+ return;
+ ccode = *attr_values;
+ }
+ }
+ else if (g_str_equal (*attr_names, "iso_639_2B_code"))
+ {
+ if (**attr_values)
+ {
+ if (strlen (*attr_values) != 3)
+ return;
+ ccode_longB = *attr_values;
+ }
+ }
+ else if (g_str_equal (*attr_names, "iso_639_2T_code"))
+ {
+ if (**attr_values)
+ {
+ if (strlen (*attr_values) != 3)
+ return;
+ ccode_longT = *attr_values;
+ }
+ }
+ else if (g_str_equal (*attr_names, "id"))
+ {
+ if (**attr_values)
+ {
+ if (strlen (*attr_values) != 2 &&
+ strlen (*attr_values) != 3)
+ return;
+ ccode_id = *attr_values;
+ }
+ }
+ else if (g_str_equal (*attr_names, "name"))
+ {
+ lang_name = *attr_values;
+ }
+
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (lang_name == NULL)
+ return;
+
+ display_name = get_display_name (lang_name);
+
+ if (ccode != NULL)
+ g_hash_table_insert (language_map,
+ pango_language_from_string (ccode),
+ g_strdup (display_name));
+
+ if (ccode_longB != NULL)
+ g_hash_table_insert (language_map,
+ pango_language_from_string (ccode_longB),
+ g_strdup (display_name));
+
+ if (ccode_longT != NULL)
+ g_hash_table_insert (language_map,
+ pango_language_from_string (ccode_longT),
+ g_strdup (display_name));
+
+ if (ccode_id != NULL)
+ g_hash_table_insert (language_map,
+ pango_language_from_string (ccode_id),
+ g_strdup (display_name));
+
+ g_free (display_name);
+}
+
+static void
+languages_variant_init (const char *variant)
+{
+ gboolean res;
+ gsize buf_len;
+ g_autofree char *buf = NULL;
+ g_autofree char *filename = NULL;
+ g_autoptr (GError) error = NULL;
+
+ bindtextdomain (variant, ISO_CODES_LOCALESDIR);
+ bind_textdomain_codeset (variant, "UTF-8");
+
+ error = NULL;
+ filename = g_strconcat (ISO_CODES_DATADIR, "/", variant, ".xml", NULL);
+ res = g_file_get_contents (filename, &buf, &buf_len, &error);
+ if (res)
+ {
+ g_autoptr (GMarkupParseContext) ctx = NULL;
+ GMarkupParser parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
+
+ ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
+
+ error = NULL;
+ res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+ if (!res)
+ g_warning ("Failed to parse '%s': %s\n", filename, error->message);
+ }
+ else
+ g_warning ("Failed to load '%s': %s\n", filename, error->message);
+}
+
+static void
+languages_init (void)
+{
+ if (language_map)
+ return;
+
+ language_map = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+ languages_variant_init ("iso_639");
+ languages_variant_init ("iso_639_3");
+}
+
+const char *
+get_language_name (PangoLanguage *language)
+{
+ languages_init ();
+
+ return (const char *) g_hash_table_lookup (language_map, language);
+}
+
+const char *
+get_language_name_for_tag (guint32 tag)
+{
+ hb_language_t lang;
+ const char *s;
+
+ lang = hb_ot_tag_to_language (tag);
+ s = hb_language_to_string (lang);
+
+ return get_language_name (pango_language_from_string (s));
+}
diff --git a/demos/gtk-demo/language-names.h b/demos/gtk-demo/language-names.h
new file mode 100644
index 0000000000..562f7ae2f8
--- /dev/null
+++ b/demos/gtk-demo/language-names.h
@@ -0,0 +1,13 @@
+#ifndef LANGUAGE_NAMES_H
+#define LANGUAGE_NAMES_H
+
+#include <pango/pango.h>
+
+G_BEGIN_DECLS
+
+const char * get_language_name (PangoLanguage *language);
+const char * get_language_name_for_tag (guint32 tag);
+
+G_END_DECLS
+
+#endif
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 0d5744762d..f4c3613215 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -94,7 +94,7 @@ gtkdemo_resources = gnome.compile_resources('gtkdemo_resources',
source_dir: '.')
executable('gtk4-demo',
- 'main.c', 'gtkfishbowl.c', demos, demos_h, gtkdemo_resources,
+ 'main.c', 'gtkfishbowl.c', 'fontplane.c', 'script-names.c', 'language-names.c', demos, demos_h, gtkdemo_resources,
c_args: gtkdemo_args,
dependencies: gtkdemo_deps,
include_directories: confinc,
diff --git a/demos/gtk-demo/script-names.c b/demos/gtk-demo/script-names.c
new file mode 100644
index 0000000000..5049c34d0b
--- /dev/null
+++ b/demos/gtk-demo/script-names.c
@@ -0,0 +1,184 @@
+#include "config.h"
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <hb-ot.h>
+
+#include "script-names.h"
+
+static struct {
+ GUnicodeScript script;
+ hb_script_t hb_script;
+ const char *name;
+} scripts[] =
+{
+ { G_UNICODE_SCRIPT_COMMON, HB_SCRIPT_COMMON, NULL },
+ { G_UNICODE_SCRIPT_INHERITED, HB_SCRIPT_INHERITED, NULL },
+ { G_UNICODE_SCRIPT_ARABIC, HB_SCRIPT_ARABIC, NC_("Script", "Arabic") },
+ { G_UNICODE_SCRIPT_ARMENIAN, HB_SCRIPT_ARMENIAN, NC_("Script", "Armenian") },
+ { G_UNICODE_SCRIPT_BENGALI, HB_SCRIPT_BENGALI, NC_("Script", "Bengali") },
+ { G_UNICODE_SCRIPT_BOPOMOFO, HB_SCRIPT_BOPOMOFO, NC_("Script", "Bopomofo") },
+ { G_UNICODE_SCRIPT_CHEROKEE, HB_SCRIPT_CHEROKEE, NC_("Script", "Cherokee") },
+ { G_UNICODE_SCRIPT_COPTIC, HB_SCRIPT_COPTIC, NC_("Script", "Coptic") },
+ { G_UNICODE_SCRIPT_CYRILLIC, HB_SCRIPT_CYRILLIC, NC_("Script", "Cyrillic") },
+ { G_UNICODE_SCRIPT_DESERET, HB_SCRIPT_DESERET, NC_("Script", "Deseret") },
+ { G_UNICODE_SCRIPT_DEVANAGARI, HB_SCRIPT_DEVANAGARI, NC_("Script", "Devanagari") },
+ { G_UNICODE_SCRIPT_ETHIOPIC, HB_SCRIPT_ETHIOPIC, NC_("Script", "Ethiopic") },
+ { G_UNICODE_SCRIPT_GEORGIAN, HB_SCRIPT_GEORGIAN, NC_("Script", "Georgian") },
+ { G_UNICODE_SCRIPT_GOTHIC, HB_SCRIPT_GOTHIC, NC_("Script", "Gothic") },
+ { G_UNICODE_SCRIPT_GREEK, HB_SCRIPT_GREEK, NC_("Script", "Greek") },
+ { G_UNICODE_SCRIPT_GUJARATI, HB_SCRIPT_GUJARATI, NC_("Script", "Gujarati") },
+ { G_UNICODE_SCRIPT_GURMUKHI, HB_SCRIPT_GURMUKHI, NC_("Script", "Gurmukhi") },
+ { G_UNICODE_SCRIPT_HAN, HB_SCRIPT_HAN, NC_("Script", "Han") },
+ { G_UNICODE_SCRIPT_HANGUL, HB_SCRIPT_HANGUL, NC_("Script", "Hangul") },
+ { G_UNICODE_SCRIPT_HEBREW, HB_SCRIPT_HEBREW, NC_("Script", "Hebrew") },
+ { G_UNICODE_SCRIPT_HIRAGANA, HB_SCRIPT_HIRAGANA, NC_("Script", "Hiragana") },
+ { G_UNICODE_SCRIPT_KANNADA, HB_SCRIPT_KANNADA, NC_("Script", "Kannada") },
+ { G_UNICODE_SCRIPT_KATAKANA, HB_SCRIPT_KATAKANA, NC_("Script", "Katakana") },
+ { G_UNICODE_SCRIPT_KHMER, HB_SCRIPT_KHMER, NC_("Script", "Khmer") },
+ { G_UNICODE_SCRIPT_LAO, HB_SCRIPT_LAO, NC_("Script", "Lao") },
+ { G_UNICODE_SCRIPT_LATIN, HB_SCRIPT_LATIN, NC_("Script", "Latin") },
+ { G_UNICODE_SCRIPT_MALAYALAM, HB_SCRIPT_MALAYALAM, NC_("Script", "Malayalam") },
+ { G_UNICODE_SCRIPT_MONGOLIAN, HB_SCRIPT_MONGOLIAN, NC_("Script", "Mongolian") },
+ { G_UNICODE_SCRIPT_MYANMAR, HB_SCRIPT_MYANMAR, NC_("Script", "Myanmar") },
+ { G_UNICODE_SCRIPT_OGHAM, HB_SCRIPT_OGHAM, NC_("Script", "Ogham") },
+ { G_UNICODE_SCRIPT_OLD_ITALIC, HB_SCRIPT_OLD_ITALIC, NC_("Script", "Old Italic") },
+ { G_UNICODE_SCRIPT_ORIYA, HB_SCRIPT_ORIYA, NC_("Script", "Oriya") },
+ { G_UNICODE_SCRIPT_RUNIC, HB_SCRIPT_RUNIC, NC_("Script", "Runic") },
+ { G_UNICODE_SCRIPT_SINHALA, HB_SCRIPT_SINHALA, NC_("Script", "Sinhala") },
+ { G_UNICODE_SCRIPT_SYRIAC, HB_SCRIPT_SYRIAC, NC_("Script", "Syriac") },
+ { G_UNICODE_SCRIPT_TAMIL, HB_SCRIPT_TAMIL, NC_("Script", "Tamil") },
+ { G_UNICODE_SCRIPT_TELUGU, HB_SCRIPT_TELUGU, NC_("Script", "Telugu") },
+ { G_UNICODE_SCRIPT_THAANA, HB_SCRIPT_THAANA, NC_("Script", "Thaana") },
+ { G_UNICODE_SCRIPT_THAI, HB_SCRIPT_THAI, NC_("Script", "Thai") },
+ { G_UNICODE_SCRIPT_TIBETAN, HB_SCRIPT_TIBETAN, NC_("Script", "Tibetan") },
+ { G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL, HB_SCRIPT_CANADIAN_ABORIGINAL, NC_("Script", "Canadian Aboriginal") },
+ { G_UNICODE_SCRIPT_YI, HB_SCRIPT_YI, NC_("Script", "Yi") },
+ { G_UNICODE_SCRIPT_TAGALOG, HB_SCRIPT_TAGALOG, NC_("Script", "Tagalog") },
+ { G_UNICODE_SCRIPT_HANUNOO, HB_SCRIPT_HANUNOO, NC_("Script", "Hanunoo") },
+ { G_UNICODE_SCRIPT_BUHID, HB_SCRIPT_BUHID, NC_("Script", "Buhid") },
+ { G_UNICODE_SCRIPT_TAGBANWA, HB_SCRIPT_TAGBANWA, NC_("Script", "Tagbanwa") },
+ { G_UNICODE_SCRIPT_BRAILLE, HB_SCRIPT_BRAILLE, NC_("Script", "Braille") },
+ { G_UNICODE_SCRIPT_CYPRIOT, HB_SCRIPT_CYPRIOT, NC_("Script", "Cypriot") },
+ { G_UNICODE_SCRIPT_LIMBU, HB_SCRIPT_LIMBU, NC_("Script", "Limbu") },
+ { G_UNICODE_SCRIPT_OSMANYA, HB_SCRIPT_OSMANYA, NC_("Script", "Osmanya") },
+ { G_UNICODE_SCRIPT_SHAVIAN, HB_SCRIPT_SHAVIAN, NC_("Script", "Shavian") },
+ { G_UNICODE_SCRIPT_LINEAR_B, HB_SCRIPT_LINEAR_B, NC_("Script", "Linear B") },
+ { G_UNICODE_SCRIPT_TAI_LE, HB_SCRIPT_TAI_LE, NC_("Script", "Tai Le") },
+ { G_UNICODE_SCRIPT_UGARITIC, HB_SCRIPT_UGARITIC, NC_("Script", "Ugaritic") },
+ { G_UNICODE_SCRIPT_NEW_TAI_LUE, HB_SCRIPT_NEW_TAI_LUE, NC_("Script", "New Tai Lue") },
+ { G_UNICODE_SCRIPT_BUGINESE, HB_SCRIPT_BUGINESE, NC_("Script", "Buginese") },
+ { G_UNICODE_SCRIPT_GLAGOLITIC, HB_SCRIPT_GLAGOLITIC, NC_("Script", "Glagolitic") },
+ { G_UNICODE_SCRIPT_TIFINAGH, HB_SCRIPT_TIFINAGH, NC_("Script", "Tifinagh") },
+ { G_UNICODE_SCRIPT_SYLOTI_NAGRI, HB_SCRIPT_SYLOTI_NAGRI, NC_("Script", "Syloti Nagri") },
+ { G_UNICODE_SCRIPT_OLD_PERSIAN, HB_SCRIPT_OLD_PERSIAN, NC_("Script", "Old Persian") },
+ { G_UNICODE_SCRIPT_KHAROSHTHI, HB_SCRIPT_KHAROSHTHI, NC_("Script", "Kharoshthi") },
+ { G_UNICODE_SCRIPT_UNKNOWN, HB_SCRIPT_UNKNOWN, NC_("Script", "Unknown") },
+ { G_UNICODE_SCRIPT_BALINESE, HB_SCRIPT_BALINESE, NC_("Script", "Balinese") },
+ { G_UNICODE_SCRIPT_CUNEIFORM, HB_SCRIPT_CUNEIFORM, NC_("Script", "Cuneiform") },
+ { G_UNICODE_SCRIPT_PHOENICIAN, HB_SCRIPT_PHOENICIAN, NC_("Script", "Phoenician") },
+ { G_UNICODE_SCRIPT_PHAGS_PA, HB_SCRIPT_PHAGS_PA, NC_("Script", "Phags-pa") },
+ { G_UNICODE_SCRIPT_NKO, HB_SCRIPT_NKO, NC_("Script", "N'Ko") },
+ { G_UNICODE_SCRIPT_KAYAH_LI, HB_SCRIPT_KAYAH_LI, NC_("Script", "Kayah Li") },
+ { G_UNICODE_SCRIPT_LEPCHA, HB_SCRIPT_LEPCHA, NC_("Script", "Lepcha") },
+ { G_UNICODE_SCRIPT_REJANG, HB_SCRIPT_REJANG, NC_("Script", "Rejang") },
+ { G_UNICODE_SCRIPT_SUNDANESE, HB_SCRIPT_SUNDANESE, NC_("Script", "Sundanese") },
+ { G_UNICODE_SCRIPT_SAURASHTRA, HB_SCRIPT_SAURASHTRA, NC_("Script", "Saurashtra") },
+ { G_UNICODE_SCRIPT_CHAM, HB_SCRIPT_CHAM, NC_("Script", "Cham") },
+ { G_UNICODE_SCRIPT_OL_CHIKI, HB_SCRIPT_OL_CHIKI, NC_("Script", "Ol Chiki") },
+ { G_UNICODE_SCRIPT_VAI, HB_SCRIPT_VAI, NC_("Script", "Vai") },
+ { G_UNICODE_SCRIPT_CARIAN, HB_SCRIPT_CARIAN, NC_("Script", "Carian") },
+ { G_UNICODE_SCRIPT_LYCIAN, HB_SCRIPT_LYCIAN, NC_("Script", "Lycian") },
+ { G_UNICODE_SCRIPT_LYDIAN, HB_SCRIPT_LYDIAN, NC_("Script", "Lydian") },
+ { G_UNICODE_SCRIPT_AVESTAN, HB_SCRIPT_AVESTAN, NC_("Script", "Avestan") },
+ { G_UNICODE_SCRIPT_BAMUM, HB_SCRIPT_BAMUM, NC_("Script", "Bamum") },
+ { G_UNICODE_SCRIPT_EGYPTIAN_HIEROGLYPHS, HB_SCRIPT_EGYPTIAN_HIEROGLYPHS, NC_("Script", "Egyptian Hieroglpyhs") },
+ { G_UNICODE_SCRIPT_IMPERIAL_ARAMAIC, HB_SCRIPT_IMPERIAL_ARAMAIC, NC_("Script", "Imperial Aramaic") },
+ { G_UNICODE_SCRIPT_INSCRIPTIONAL_PAHLAVI, HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, NC_("Script", "Inscriptional Pahlavi") },
+ { G_UNICODE_SCRIPT_INSCRIPTIONAL_PARTHIAN, HB_SCRIPT_INSCRIPTIONAL_PARTHIAN, NC_("Script", "Inscriptional Parthian") },
+ { G_UNICODE_SCRIPT_JAVANESE, HB_SCRIPT_JAVANESE, NC_("Script", "Javanese") },
+ { G_UNICODE_SCRIPT_KAITHI, HB_SCRIPT_KAITHI, NC_("Script", "Kaithi") },
+ { G_UNICODE_SCRIPT_LISU, HB_SCRIPT_LISU, NC_("Script", "Lisu") },
+ { G_UNICODE_SCRIPT_MEETEI_MAYEK, HB_SCRIPT_MEETEI_MAYEK, NC_("Script", "Meetei Mayek") },
+ { G_UNICODE_SCRIPT_OLD_SOUTH_ARABIAN, HB_SCRIPT_OLD_SOUTH_ARABIAN, NC_("Script", "Old South Arabian") },
+ { G_UNICODE_SCRIPT_OLD_TURKIC, HB_SCRIPT_OLD_TURKIC, NC_("Script", "Old Turkic") },
+ { G_UNICODE_SCRIPT_SAMARITAN, HB_SCRIPT_SAMARITAN, NC_("Script", "Samaritan") },
+ { G_UNICODE_SCRIPT_TAI_THAM, HB_SCRIPT_TAI_THAM, NC_("Script", "Tai Tham") },
+ { G_UNICODE_SCRIPT_TAI_VIET, HB_SCRIPT_TAI_VIET, NC_("Script", "Tai Viet") },
+ { G_UNICODE_SCRIPT_BATAK, HB_SCRIPT_BATAK, NC_("Script", "Batak") },
+ { G_UNICODE_SCRIPT_BRAHMI, HB_SCRIPT_BRAHMI, NC_("Script", "Brahmi") },
+ { G_UNICODE_SCRIPT_MANDAIC, HB_SCRIPT_MANDAIC, NC_("Script", "Mandaic") },
+ { G_UNICODE_SCRIPT_CHAKMA, HB_SCRIPT_CHAKMA, NC_("Script", "Chakma") },
+ { G_UNICODE_SCRIPT_MEROITIC_CURSIVE, HB_SCRIPT_MEROITIC_CURSIVE, NC_("Script", "Meroitic Cursive") },
+ { G_UNICODE_SCRIPT_MEROITIC_HIEROGLYPHS, HB_SCRIPT_MEROITIC_HIEROGLYPHS, NC_("Script", "Meroitic Hieroglyphs") },
+ { G_UNICODE_SCRIPT_MIAO, HB_SCRIPT_MIAO, NC_("Script", "Miao") },
+ { G_UNICODE_SCRIPT_SHARADA, HB_SCRIPT_SHARADA, NC_("Script", "Sharada") },
+ { G_UNICODE_SCRIPT_SORA_SOMPENG, HB_SCRIPT_SORA_SOMPENG, NC_("Script", "Sora Sompeng") },
+ { G_UNICODE_SCRIPT_TAKRI, HB_SCRIPT_TAKRI, NC_("Script", "Takri") },
+ { G_UNICODE_SCRIPT_BASSA_VAH, HB_SCRIPT_BASSA_VAH, NC_("Script", "Bassa") },
+ { G_UNICODE_SCRIPT_CAUCASIAN_ALBANIAN, HB_SCRIPT_CAUCASIAN_ALBANIAN, NC_("Script", "Caucasian Albanian") },
+ { G_UNICODE_SCRIPT_DUPLOYAN, HB_SCRIPT_DUPLOYAN, NC_("Script", "Duployan") },
+ { G_UNICODE_SCRIPT_ELBASAN, HB_SCRIPT_ELBASAN, NC_("Script", "Elbasan") },
+ { G_UNICODE_SCRIPT_GRANTHA, HB_SCRIPT_GRANTHA, NC_("Script", "Grantha") },
+ { G_UNICODE_SCRIPT_KHOJKI, HB_SCRIPT_KHOJKI, NC_("Script", "Kjohki") },
+ { G_UNICODE_SCRIPT_KHUDAWADI, HB_SCRIPT_KHUDAWADI, NC_("Script", "Khudawadi, Sindhi") },
+ { G_UNICODE_SCRIPT_LINEAR_A, HB_SCRIPT_LINEAR_A, NC_("Script", "Linear A") },
+ { G_UNICODE_SCRIPT_MAHAJANI, HB_SCRIPT_MAHAJANI, NC_("Script", "Mahajani") },
+ { G_UNICODE_SCRIPT_MANICHAEAN, HB_SCRIPT_MANICHAEAN, NC_("Script", "Manichaean") },
+ { G_UNICODE_SCRIPT_MENDE_KIKAKUI, HB_SCRIPT_MENDE_KIKAKUI, NC_("Script", "Mende Kikakui") },
+ { G_UNICODE_SCRIPT_MODI, HB_SCRIPT_MODI, NC_("Script", "Modi") },
+ { G_UNICODE_SCRIPT_MRO, HB_SCRIPT_MRO, NC_("Script", "Mro") },
+ { G_UNICODE_SCRIPT_NABATAEAN, HB_SCRIPT_NABATAEAN, NC_("Script", "Nabataean") },
+ { G_UNICODE_SCRIPT_OLD_NORTH_ARABIAN, HB_SCRIPT_OLD_NORTH_ARABIAN, NC_("Script", "Old North Arabian") },
+ { G_UNICODE_SCRIPT_OLD_PERMIC, HB_SCRIPT_OLD_PERMIC, NC_("Script", "Old Permic") },
+ { G_UNICODE_SCRIPT_PAHAWH_HMONG, HB_SCRIPT_PAHAWH_HMONG, NC_("Script", "Pahawh Hmong") },
+ { G_UNICODE_SCRIPT_PALMYRENE, HB_SCRIPT_PALMYRENE, NC_("Script", "Palmyrene") },
+ { G_UNICODE_SCRIPT_PAU_CIN_HAU, HB_SCRIPT_PAU_CIN_HAU, NC_("Script", "Pau Cin Hau") },
+ { G_UNICODE_SCRIPT_PSALTER_PAHLAVI, HB_SCRIPT_PSALTER_PAHLAVI, NC_("Script", "Psalter Pahlavi") },
+ { G_UNICODE_SCRIPT_SIDDHAM, HB_SCRIPT_SIDDHAM, NC_("Script", "Siddham") },
+ { G_UNICODE_SCRIPT_TIRHUTA, HB_SCRIPT_TIRHUTA, NC_("Script", "Tirhuta") },
+ { G_UNICODE_SCRIPT_WARANG_CITI, HB_SCRIPT_WARANG_CITI, NC_("Script", "Warang Citi") },
+ { G_UNICODE_SCRIPT_AHOM, HB_SCRIPT_AHOM, NC_("Script", "Ahom") },
+ { G_UNICODE_SCRIPT_ANATOLIAN_HIEROGLYPHS, HB_SCRIPT_ANATOLIAN_HIEROGLYPHS, NC_("Script", "Anatolian Hieroglyphs") },
+ { G_UNICODE_SCRIPT_HATRAN, HB_SCRIPT_HATRAN, NC_("Script", "Hatran") },
+ { G_UNICODE_SCRIPT_MULTANI, HB_SCRIPT_MULTANI, NC_("Script", "Multani") },
+ { G_UNICODE_SCRIPT_OLD_HUNGARIAN, HB_SCRIPT_OLD_HUNGARIAN, NC_("Script", "Old Hungarian") },
+ { G_UNICODE_SCRIPT_SIGNWRITING, HB_SCRIPT_SIGNWRITING, NC_("Script", "Signwriting") },
+ { G_UNICODE_SCRIPT_ADLAM, HB_SCRIPT_ADLAM, NC_("Script", "Adlam") },
+ { G_UNICODE_SCRIPT_BHAIKSUKI, HB_SCRIPT_BHAIKSUKI, NC_("Script", "Bhaiksuki") },
+ { G_UNICODE_SCRIPT_MARCHEN, HB_SCRIPT_MARCHEN, NC_("Script", "Marchen") },
+ { G_UNICODE_SCRIPT_NEWA, HB_SCRIPT_NEWA, NC_("Script", "Newa") },
+ { G_UNICODE_SCRIPT_OSAGE, HB_SCRIPT_OSAGE, NC_("Script", "Osage") },
+ { G_UNICODE_SCRIPT_TANGUT, HB_SCRIPT_TANGUT, NC_("Script", "Tangut") },
+ { G_UNICODE_SCRIPT_MASARAM_GONDI, HB_SCRIPT_INVALID, NC_("Script", "Masaram Gondi") },
+ { G_UNICODE_SCRIPT_NUSHU, HB_SCRIPT_INVALID, NC_("Script", "Nushu") },
+ { G_UNICODE_SCRIPT_SOYOMBO, HB_SCRIPT_INVALID, NC_("Script", "Soyombo") },
+ { G_UNICODE_SCRIPT_ZANABAZAR_SQUARE, HB_SCRIPT_INVALID, NC_("Script", "Zanabazar Square") },
+};
+
+const char *
+get_script_name (GUnicodeScript script)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (scripts); i++)
+ {
+ if (scripts[i].script == script)
+ return g_dpgettext2 (GETTEXT_PACKAGE, "Script", scripts[i].name);
+ }
+
+ return NULL;
+}
+
+const char *
+get_script_name_for_tag (guint32 tag)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (scripts); i++)
+ {
+ if (scripts[i].hb_script == hb_script_from_iso15924_tag (tag))
+ return g_dpgettext2 (GETTEXT_PACKAGE, "Script", scripts[i].name);
+ }
+
+ return NULL;
+}
diff --git a/demos/gtk-demo/script-names.h b/demos/gtk-demo/script-names.h
new file mode 100644
index 0000000000..3036c05b56
--- /dev/null
+++ b/demos/gtk-demo/script-names.h
@@ -0,0 +1,13 @@
+#ifndef SCRIPT_NAMES_H
+#define SCRIPT_NAMES_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+const char * get_script_name (GUnicodeScript script);
+const char * get_script_name_for_tag (guint32 tag);
+
+G_END_DECLS
+
+#endif