mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-28 22:41:43 +00:00
Implement font-feature-settings
This is a missing part of the CSS font level 3 module.
This commit is contained in:
parent
6042b82964
commit
22f9562928
296
gtk/gtkcssfontfeaturesvalue.c
Normal file
296
gtk/gtkcssfontfeaturesvalue.c
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 2017 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/>.
|
||||||
|
*
|
||||||
|
* Author: Matthias Clasen
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gtkcsstypesprivate.h"
|
||||||
|
#include "gtkcssparserprivate.h"
|
||||||
|
#include "gtkcssnumbervalueprivate.h"
|
||||||
|
#include "gtkcssfontfeaturesvalueprivate.h"
|
||||||
|
|
||||||
|
struct _GtkCssValue {
|
||||||
|
GTK_CSS_VALUE_BASE
|
||||||
|
GHashTable *features;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GtkCssValue *default_font_features;
|
||||||
|
|
||||||
|
static GtkCssValue *gtk_css_font_features_value_new_empty (void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_font_features_value_add_feature (GtkCssValue *value,
|
||||||
|
const char *name,
|
||||||
|
GtkCssValue *val)
|
||||||
|
{
|
||||||
|
g_hash_table_insert (value->features, g_strdup (name), val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_value_font_features_free (GtkCssValue *value)
|
||||||
|
{
|
||||||
|
g_hash_table_unref (value->features);
|
||||||
|
|
||||||
|
g_slice_free (GtkCssValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
gtk_css_value_font_features_compute (GtkCssValue *specified,
|
||||||
|
guint property_id,
|
||||||
|
GtkStyleProvider *provider,
|
||||||
|
GtkCssStyle *style,
|
||||||
|
GtkCssStyle *parent_style)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer name, val;
|
||||||
|
GtkCssValue *computed_val;
|
||||||
|
GtkCssValue *result;
|
||||||
|
gboolean changes = FALSE;
|
||||||
|
|
||||||
|
result = gtk_css_font_features_value_new_empty ();
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, specified->features);
|
||||||
|
while (g_hash_table_iter_next (&iter, &name, &val))
|
||||||
|
{
|
||||||
|
computed_val = _gtk_css_value_compute (val, property_id, provider, style, parent_style);
|
||||||
|
changes |= computed_val != val;
|
||||||
|
gtk_css_font_features_value_add_feature (result, name, computed_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changes)
|
||||||
|
{
|
||||||
|
_gtk_css_value_unref (result);
|
||||||
|
result = _gtk_css_value_ref (specified);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_css_value_font_features_equal (const GtkCssValue *value1,
|
||||||
|
const GtkCssValue *value2)
|
||||||
|
{
|
||||||
|
gpointer name, val1, val2;
|
||||||
|
GHashTableIter iter;
|
||||||
|
|
||||||
|
if (g_hash_table_size (value1->features) != g_hash_table_size (value2->features))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, value1->features);
|
||||||
|
while (g_hash_table_iter_next (&iter, &name, &val1))
|
||||||
|
{
|
||||||
|
val2 = g_hash_table_lookup (value2->features, name);
|
||||||
|
if (val2 == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!_gtk_css_value_equal (val1, val2))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
gtk_css_value_font_features_transition (GtkCssValue *start,
|
||||||
|
GtkCssValue *end,
|
||||||
|
guint property_id,
|
||||||
|
double progress)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
GtkCssValue *start_val, *end_val;
|
||||||
|
GHashTableIter iter;
|
||||||
|
GtkCssValue *result, *transition;
|
||||||
|
|
||||||
|
/* XXX: For value that are only in start or end but not both,
|
||||||
|
* we don't transition but just keep the value.
|
||||||
|
* That causes an abrupt transition to the new value at the end.
|
||||||
|
*/
|
||||||
|
|
||||||
|
result = gtk_css_font_features_value_new_empty ();
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, start->features);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&start_val))
|
||||||
|
{
|
||||||
|
end_val = g_hash_table_lookup (end->features, name);
|
||||||
|
if (end_val == NULL)
|
||||||
|
transition = _gtk_css_value_ref (start_val);
|
||||||
|
else
|
||||||
|
transition = _gtk_css_value_transition (start_val, end_val, property_id, progress);
|
||||||
|
|
||||||
|
gtk_css_font_features_value_add_feature (result, name, transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, end->features);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&end_val))
|
||||||
|
{
|
||||||
|
start_val = g_hash_table_lookup (start->features, name);
|
||||||
|
if (start_val != NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gtk_css_font_features_value_add_feature (result, name, _gtk_css_value_ref (end_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_css_value_font_features_print (const GtkCssValue *value,
|
||||||
|
GString *string)
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
const char *name;
|
||||||
|
GtkCssValue *val;
|
||||||
|
gboolean first = TRUE;
|
||||||
|
|
||||||
|
if (value == default_font_features)
|
||||||
|
{
|
||||||
|
g_string_append (string, "normal");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, value->features);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&val))
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
first = FALSE;
|
||||||
|
else
|
||||||
|
g_string_append (string, ", ");
|
||||||
|
g_string_append_printf (string, "\"%s\" ", name);
|
||||||
|
_gtk_css_value_print (val, string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GtkCssValueClass GTK_CSS_VALUE_FONT_FEATURES = {
|
||||||
|
gtk_css_value_font_features_free,
|
||||||
|
gtk_css_value_font_features_compute,
|
||||||
|
gtk_css_value_font_features_equal,
|
||||||
|
gtk_css_value_font_features_transition,
|
||||||
|
gtk_css_value_font_features_print
|
||||||
|
};
|
||||||
|
|
||||||
|
static GtkCssValue *
|
||||||
|
gtk_css_font_features_value_new_empty (void)
|
||||||
|
{
|
||||||
|
GtkCssValue *result;
|
||||||
|
|
||||||
|
result = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_FONT_FEATURES);
|
||||||
|
result->features = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free,
|
||||||
|
(GDestroyNotify) _gtk_css_value_unref);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkCssValue *
|
||||||
|
gtk_css_font_features_value_new_default (void)
|
||||||
|
{
|
||||||
|
if (default_font_features == NULL)
|
||||||
|
default_font_features = gtk_css_font_features_value_new_empty ();
|
||||||
|
|
||||||
|
return _gtk_css_value_ref (default_font_features);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_valid_opentype_tag (const char *s)
|
||||||
|
{
|
||||||
|
if (strlen (s) != 4)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (s[0] < 0x20 || s[0] > 0x7e ||
|
||||||
|
s[1] < 0x20 || s[1] > 0x7e ||
|
||||||
|
s[2] < 0x20 || s[2] > 0x7e ||
|
||||||
|
s[3] < 0x20 || s[3] > 0x7e)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkCssValue *
|
||||||
|
gtk_css_font_features_value_parse (GtkCssParser *parser)
|
||||||
|
{
|
||||||
|
GtkCssValue *result, *val;
|
||||||
|
char *name;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
if (_gtk_css_parser_try (parser, "normal", TRUE))
|
||||||
|
return gtk_css_font_features_value_new_default ();
|
||||||
|
|
||||||
|
result = gtk_css_font_features_value_new_empty ();
|
||||||
|
|
||||||
|
do {
|
||||||
|
_gtk_css_parser_skip_whitespace (parser);
|
||||||
|
name = _gtk_css_parser_read_string (parser);
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
_gtk_css_value_unref (result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_valid_opentype_tag (name))
|
||||||
|
{
|
||||||
|
_gtk_css_parser_error (parser, "Not a valid OpenType tag.");
|
||||||
|
g_free (name);
|
||||||
|
_gtk_css_value_unref (result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_gtk_css_parser_try (parser, "on", TRUE))
|
||||||
|
val = _gtk_css_number_value_new (1.0, GTK_CSS_NUMBER);
|
||||||
|
else if (_gtk_css_parser_try (parser, "off", TRUE))
|
||||||
|
val = _gtk_css_number_value_new (0.0, GTK_CSS_NUMBER);
|
||||||
|
else if (_gtk_css_parser_try_int (parser, &num))
|
||||||
|
val = _gtk_css_number_value_new ((double)num, GTK_CSS_NUMBER);
|
||||||
|
else
|
||||||
|
val = _gtk_css_number_value_new (1.0, GTK_CSS_NUMBER);
|
||||||
|
|
||||||
|
gtk_css_font_features_value_add_feature (result, name, val);
|
||||||
|
g_free (name);
|
||||||
|
} while (_gtk_css_parser_try (parser, ",", TRUE));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gtk_css_font_features_value_get_features (GtkCssValue *value)
|
||||||
|
{
|
||||||
|
GtkCssValue *val;
|
||||||
|
GHashTableIter iter;
|
||||||
|
gboolean first = TRUE;
|
||||||
|
const char *name;
|
||||||
|
GString *string;
|
||||||
|
|
||||||
|
g_return_val_if_fail (value->class == >K_CSS_VALUE_FONT_FEATURES, NULL);
|
||||||
|
|
||||||
|
if (value == default_font_features)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
string = g_string_new ("");
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, value->features);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&val))
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
first = FALSE;
|
||||||
|
else
|
||||||
|
g_string_append (string, ", ");
|
||||||
|
g_string_append_printf (string, "%s %d", name, (int)_gtk_css_number_value_get (val, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_string_free (string, FALSE);
|
||||||
|
}
|
36
gtk/gtkcssfontfeaturesvalueprivate.h
Normal file
36
gtk/gtkcssfontfeaturesvalueprivate.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2017 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.1 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/>.
|
||||||
|
*
|
||||||
|
* Authors: Matthias Clasen
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_CSS_FONT_FEATURES_VALUE_PRIVATE_H__
|
||||||
|
#define __GTK_CSS_FONT_FEATURES_PRIVATE_H__
|
||||||
|
|
||||||
|
#include "gtkcssparserprivate.h"
|
||||||
|
#include "gtkcssvalueprivate.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
GtkCssValue * gtk_css_font_features_value_new_default (void);
|
||||||
|
|
||||||
|
GtkCssValue * gtk_css_font_features_value_parse (GtkCssParser *parser);
|
||||||
|
|
||||||
|
char * gtk_css_font_features_value_get_features (GtkCssValue *value);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_CSS_FONT_FEATURES_VALUE_PRIVATE_H__ */
|
@ -32,6 +32,7 @@
|
|||||||
#include "gtkcsssectionprivate.h"
|
#include "gtkcsssectionprivate.h"
|
||||||
#include "gtkcssshorthandpropertyprivate.h"
|
#include "gtkcssshorthandpropertyprivate.h"
|
||||||
#include "gtkcssstringvalueprivate.h"
|
#include "gtkcssstringvalueprivate.h"
|
||||||
|
#include "gtkcssfontfeaturesvalueprivate.h"
|
||||||
#include "gtkcssstylepropertyprivate.h"
|
#include "gtkcssstylepropertyprivate.h"
|
||||||
#include "gtkcsstransitionprivate.h"
|
#include "gtkcsstransitionprivate.h"
|
||||||
#include "gtkstyleanimationprivate.h"
|
#include "gtkstyleanimationprivate.h"
|
||||||
@ -238,6 +239,7 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
|
|||||||
GtkCssFontVariantNumeric numeric;
|
GtkCssFontVariantNumeric numeric;
|
||||||
GtkCssFontVariantEastAsian east_asian;
|
GtkCssFontVariantEastAsian east_asian;
|
||||||
GString *s;
|
GString *s;
|
||||||
|
char *settings;
|
||||||
|
|
||||||
/* text-decoration */
|
/* text-decoration */
|
||||||
decoration_line = _gtk_css_text_decoration_line_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TEXT_DECORATION_LINE));
|
decoration_line = _gtk_css_text_decoration_line_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_TEXT_DECORATION_LINE));
|
||||||
@ -424,6 +426,16 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
|
|||||||
append_separated (s, "ruby 1");
|
append_separated (s, "ruby 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_print ("before: %s\n", s->str);
|
||||||
|
value = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS);
|
||||||
|
settings = gtk_css_font_features_value_get_features (value);
|
||||||
|
if (settings)
|
||||||
|
{
|
||||||
|
append_separated (s, settings);
|
||||||
|
g_free (settings);
|
||||||
|
}
|
||||||
|
g_print ("after: %s\n", s->str);
|
||||||
|
|
||||||
attrs = add_pango_attr (attrs, pango_attr_font_features_new (s->str));
|
attrs = add_pango_attr (attrs, pango_attr_font_features_new (s->str));
|
||||||
g_string_free (s, TRUE);
|
g_string_free (s, TRUE);
|
||||||
|
|
||||||
|
@ -657,6 +657,12 @@ parse_font_variant_east_asian (GtkCssStyleProperty *property,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GtkCssValue *
|
static GtkCssValue *
|
||||||
|
parse_font_feature_settings (GtkCssStyleProperty *property,
|
||||||
|
GtkCssParser *parser)
|
||||||
|
{
|
||||||
|
return gtk_css_font_features_value_parse (parser);
|
||||||
|
}
|
||||||
|
|
||||||
box_shadow_value_parse (GtkCssStyleProperty *property,
|
box_shadow_value_parse (GtkCssStyleProperty *property,
|
||||||
GtkCssParser *parser)
|
GtkCssParser *parser)
|
||||||
{
|
{
|
||||||
@ -1800,4 +1806,12 @@ _gtk_css_style_property_init_properties (void)
|
|||||||
color_parse,
|
color_parse,
|
||||||
color_query,
|
color_query,
|
||||||
_gtk_css_color_value_new_current_color ());
|
_gtk_css_color_value_new_current_color ());
|
||||||
|
gtk_css_style_property_register ("font-feature-settings",
|
||||||
|
GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
|
||||||
|
GTK_CSS_AFFECTS_TEXT_ATTRS | GTK_CSS_AFFECTS_TEXT_SIZE,
|
||||||
|
parse_font_feature_settings,
|
||||||
|
NULL,
|
||||||
|
gtk_css_font_features_value_new_default ());
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,7 @@ enum { /*< skip >*/
|
|||||||
GTK_CSS_PROPERTY_GTK_KEY_BINDINGS,
|
GTK_CSS_PROPERTY_GTK_KEY_BINDINGS,
|
||||||
GTK_CSS_PROPERTY_CARET_COLOR,
|
GTK_CSS_PROPERTY_CARET_COLOR,
|
||||||
GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR,
|
GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR,
|
||||||
|
GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS,
|
||||||
/* add more */
|
/* add more */
|
||||||
GTK_CSS_PROPERTY_N_PROPERTIES
|
GTK_CSS_PROPERTY_N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
@ -85,6 +85,7 @@ gtk_public_sources = files([
|
|||||||
'gtkcsseasevalue.c',
|
'gtkcsseasevalue.c',
|
||||||
'gtkcssenumvalue.c',
|
'gtkcssenumvalue.c',
|
||||||
'gtkcssfiltervalue.c',
|
'gtkcssfiltervalue.c',
|
||||||
|
'gtkcssfontfeaturesvalue.c',
|
||||||
'gtkcssiconthemevalue.c',
|
'gtkcssiconthemevalue.c',
|
||||||
'gtkcssimage.c',
|
'gtkcssimage.c',
|
||||||
'gtkcssimagebuiltin.c',
|
'gtkcssimagebuiltin.c',
|
||||||
|
Loading…
Reference in New Issue
Block a user