[gtk+] css: Implement font-variant-ligatures



commit c4cbe5fecafcd2b244981769086081d4fbfb1fc2
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Sep 17 23:52:04 2017 -0400

    css: Implement font-variant-ligatures
    
    This gets translated into corresponding OpenType features.

 gtk/gtkcssstyle.c             |   38 ++++++++++++++++-
 gtk/gtkcssstylepropertyimpl.c |   93 +++++++++++++++++++++++++++++++++++++++++
 gtk/gtkcsstypesprivate.h      |    1 +
 3 files changed, 130 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkcssstyle.c b/gtk/gtkcssstyle.c
index dcce352..44a9f1c 100644
--- a/gtk/gtkcssstyle.c
+++ b/gtk/gtkcssstyle.c
@@ -226,6 +226,9 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
   const GdkRGBA *decoration_color;
   gint letter_spacing;
   GtkCssValue *kerning;
+  GtkCssValue *ligatures;
+  GString *s;
+  int i;
 
   /* text-decoration */
   decoration_line = _gtk_css_text_decoration_line_value_get (gtk_css_style_get_value (style, 
GTK_CSS_PROPERTY_TEXT_DECORATION_LINE));
@@ -261,11 +264,42 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
       attrs = add_pango_attr (attrs, pango_attr_letter_spacing_new (letter_spacing * PANGO_SCALE));
     }
 
+  /* OpenType features */
+  s = g_string_new ("");
+
   kerning = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_KERNING);
   if (strcmp (_gtk_css_ident_value_get (kerning), "normal") == 0)
-    attrs = add_pango_attr (attrs, pango_attr_font_features_new ("kern 1"));
+    g_string_append (s, "kern 1");
   else if (strcmp (_gtk_css_ident_value_get (kerning), "none") == 0)
-    attrs = add_pango_attr (attrs, pango_attr_font_features_new ("kern 0"));
+    g_string_append (s, "kern 0");
+
+  ligatures = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES);
+  for (i = 0; i < _gtk_css_array_value_get_n_values (ligatures); i++)
+    {
+      GtkCssValue *value = _gtk_css_array_value_get_nth (ligatures, i);
+      if (s->len > 0) g_string_append (s, ", ");
+      if (strcmp (_gtk_css_ident_value_get (value), "none") == 0)
+        g_string_append (s, "liga 0, clig 0, dlig 0, hlig 0, calt 0");
+      else if (strcmp (_gtk_css_ident_value_get (value), "common-ligatures") == 0)
+        g_string_append (s, "liga 1, clig 1");
+      else if (strcmp (_gtk_css_ident_value_get (value), "no-common-ligatures") == 0)
+        g_string_append (s, "liga 0, clig 0");
+      else if (strcmp (_gtk_css_ident_value_get (value), "discretionary-ligatures") == 0)
+        g_string_append (s, "dlig 1");
+      else if (strcmp (_gtk_css_ident_value_get (value), "no-discretionary-ligatures") == 0)
+        g_string_append (s, "dlig 0");
+      else if (strcmp (_gtk_css_ident_value_get (value), "historical-ligatures") == 0)
+        g_string_append (s, "hlig 1");
+      else if (strcmp (_gtk_css_ident_value_get (value), "no-historical-ligatures") == 0)
+        g_string_append (s, "hlig 0");
+      else if (strcmp (_gtk_css_ident_value_get (value), "contextual") == 0)
+        g_string_append (s, "calt 1");
+      else if (strcmp (_gtk_css_ident_value_get (value), "no-contextual") == 0)
+        g_string_append (s, "calt 0");
+    }
+
+  attrs = add_pango_attr (attrs, pango_attr_font_features_new (s->str));
+  g_string_free (s, TRUE);
 
   return attrs;
 }
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index bf98160..a07fe1b 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -543,6 +543,91 @@ parse_font_kerning (GtkCssStyleProperty *property,
   return value;
 }
 
+static gboolean
+value_is_done_parsing (GtkCssParser *parser)
+{
+  return _gtk_css_parser_is_eof (parser) ||
+         _gtk_css_parser_begins_with (parser, ',') ||
+         _gtk_css_parser_begins_with (parser, ';') ||
+         _gtk_css_parser_begins_with (parser, '}');
+}
+
+static GtkCssValue *
+parse_font_variant_ligatures (GtkCssStyleProperty *property,
+                              GtkCssParser        *parser)
+{
+  GtkCssValue *value = NULL;
+
+  if (_gtk_css_parser_try (parser, "normal", TRUE))
+    value = _gtk_css_array_value_new (_gtk_css_ident_value_new ("normal"));
+  else if (_gtk_css_parser_try (parser, "none", TRUE))
+    value = _gtk_css_array_value_new (_gtk_css_ident_value_new ("none"));
+  else
+    {
+      GtkCssValue *values[4] = { NULL, NULL, NULL, NULL };
+      guint n_values = 0;
+      guint old_n;
+      gboolean common = FALSE;
+      gboolean discretionary = FALSE;
+      gboolean historical = FALSE;
+      gboolean contextual = FALSE;
+
+      do {
+        old_n = n_values;
+        if (!common)
+          {
+            values[n_values] = _gtk_css_ident_value_try (parser, "common-ligatures",
+                                                                 "no-common-ligatures", NULL);
+            if (values[n_values])
+              {
+                n_values++;
+                common = TRUE;
+              }
+          }
+        if (!discretionary)
+          {
+            values[n_values] = _gtk_css_ident_value_try (parser, "discretionary-ligatures",
+                                                                 "no-discretionary-ligatures", NULL);
+            if (values[n_values])
+              {
+                n_values++;
+                discretionary = TRUE;
+              }
+          }
+        if (!historical)
+          {
+            values[n_values] = _gtk_css_ident_value_try (parser, "historical-ligatures",
+                                                                 "no-historical-ligatures",
+                                                                 NULL);
+            if (values[n_values])
+              {
+                n_values++;
+                historical = TRUE;
+              }
+          }
+        if (!contextual)
+          {
+            values[n_values] = _gtk_css_ident_value_try (parser, "contextual",
+                                                                 "no-contextual", NULL);
+            if (values[n_values])
+              {
+                n_values++;
+                contextual = TRUE;
+              }
+          }
+        if (old_n == n_values)
+          {
+            _gtk_css_parser_error (parser, "Not a valid value");
+            return NULL;
+          }
+      } while (!value_is_done_parsing (parser));
+
+      value = _gtk_css_array_value_new_from_array (values, n_values);
+    }
+
+  return value;
+}
+
 static GtkCssValue *
 box_shadow_value_parse (GtkCssStyleProperty *property,
                         GtkCssParser        *parser)
@@ -1036,6 +1121,14 @@ _gtk_css_style_property_init_properties (void)
                                           parse_font_kerning,
                                           NULL,
                                           _gtk_css_ident_value_new ("auto"));
+  gtk_css_style_property_register        ("font-variant-ligatures",
+                                          GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES,
+                                          G_TYPE_NONE,
+                                          0,
+                                          GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
+                                          parse_font_variant_ligatures,
+                                          NULL,
+                                          _gtk_css_array_value_new (_gtk_css_ident_value_new ("normal")));
 
   gtk_css_style_property_register        ("text-shadow",
                                           GTK_CSS_PROPERTY_TEXT_SHADOW,
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index b4f79fb..2ff6750 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -164,6 +164,7 @@ enum { /*< skip >*/
   GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR,
   GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE,
   GTK_CSS_PROPERTY_FONT_KERNING,
+  GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES,
   GTK_CSS_PROPERTY_TEXT_SHADOW,
   GTK_CSS_PROPERTY_BOX_SHADOW,
   GTK_CSS_PROPERTY_MARGIN_TOP,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]