mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 19:00:08 +00:00
Implement font-variation-settings
This is a CSS font level 4 property that lets us use font variation settings from css.
This commit is contained in:
parent
f259aa7e76
commit
fb51e438e9
@ -322,6 +322,15 @@ We use <literallayout> for syntax productions, and each line is put in a <code>
|
||||
<entry><ulink url="https://www.w3.org/TR/css3-fonts/#font-feature-settings-prop">CSS3</ulink></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><phrase role="nowrap">font-variation-settings</phrase></entry>
|
||||
<entry><code>normal | [ 〈string〉〈number〉]#</code></entry>
|
||||
<entry>normal</entry>
|
||||
<entry>✓</entry>
|
||||
<entry>✓</entry>
|
||||
<entry><ulink url="https://www.w3.org/TR/css-fonts-4/#font-variation-settings-def">CSS4</ulink></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
<tgroup cols="5">
|
||||
|
294
gtk/gtkcssfontvariationsvalue.c
Normal file
294
gtk/gtkcssfontvariationsvalue.c
Normal file
@ -0,0 +1,294 @@
|
||||
/* 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 "gtkcssparserprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkcssfontvariationsvalueprivate.h"
|
||||
|
||||
struct _GtkCssValue {
|
||||
GTK_CSS_VALUE_BASE
|
||||
GHashTable *axes;
|
||||
};
|
||||
|
||||
static GtkCssValue *default_font_variations;
|
||||
|
||||
static GtkCssValue *gtk_css_font_variations_value_new_empty (void);
|
||||
|
||||
static void
|
||||
gtk_css_font_variations_value_add_axis (GtkCssValue *value,
|
||||
const char *name,
|
||||
GtkCssValue *coord)
|
||||
{
|
||||
g_hash_table_insert (value->axes, g_strdup (name), coord);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_css_value_font_variations_free (GtkCssValue *value)
|
||||
{
|
||||
g_hash_table_unref (value->axes);
|
||||
|
||||
g_slice_free (GtkCssValue, value);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_value_font_variations_compute (GtkCssValue *specified,
|
||||
guint property_id,
|
||||
GtkStyleProvider *provider,
|
||||
GtkCssStyle *style,
|
||||
GtkCssStyle *parent_style)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer name, coord;
|
||||
GtkCssValue *computed_coord;
|
||||
GtkCssValue *result;
|
||||
gboolean changes = FALSE;
|
||||
|
||||
result = gtk_css_font_variations_value_new_empty ();
|
||||
|
||||
g_hash_table_iter_init (&iter, specified->axes);
|
||||
while (g_hash_table_iter_next (&iter, &name, &coord))
|
||||
{
|
||||
computed_coord = _gtk_css_value_compute (coord, property_id, provider, style, parent_style);
|
||||
changes |= computed_coord != coord;
|
||||
gtk_css_font_variations_value_add_axis (result, name, computed_coord);
|
||||
}
|
||||
|
||||
if (!changes)
|
||||
{
|
||||
_gtk_css_value_unref (result);
|
||||
result = _gtk_css_value_ref (specified);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_value_font_variations_equal (const GtkCssValue *value1,
|
||||
const GtkCssValue *value2)
|
||||
{
|
||||
gpointer name, coord1, coord2;
|
||||
GHashTableIter iter;
|
||||
|
||||
if (g_hash_table_size (value1->axes) != g_hash_table_size (value2->axes))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_iter_init (&iter, value1->axes);
|
||||
while (g_hash_table_iter_next (&iter, &name, &coord1))
|
||||
{
|
||||
coord2 = g_hash_table_lookup (value2->axes, name);
|
||||
if (coord2 == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!_gtk_css_value_equal (coord1, coord2))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_value_font_variations_transition (GtkCssValue *start,
|
||||
GtkCssValue *end,
|
||||
guint property_id,
|
||||
double progress)
|
||||
{
|
||||
const char *name;
|
||||
GtkCssValue *start_coord, *end_coord;
|
||||
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_variations_value_new_empty ();
|
||||
|
||||
g_hash_table_iter_init (&iter, start->axes);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&start_coord))
|
||||
{
|
||||
end_coord = g_hash_table_lookup (end->axes, name);
|
||||
if (end_coord == NULL)
|
||||
transition = _gtk_css_value_ref (start_coord);
|
||||
else
|
||||
transition = _gtk_css_value_transition (start_coord, end_coord, property_id, progress);
|
||||
|
||||
gtk_css_font_variations_value_add_axis (result, name, transition);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, end->axes);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&end_coord))
|
||||
{
|
||||
start_coord = g_hash_table_lookup (start->axes, name);
|
||||
if (start_coord != NULL)
|
||||
continue;
|
||||
|
||||
gtk_css_font_variations_value_add_axis (result, name, _gtk_css_value_ref (end_coord));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_value_font_variations_print (const GtkCssValue *value,
|
||||
GString *string)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
const char *name;
|
||||
GtkCssValue *coord;
|
||||
gboolean first = TRUE;
|
||||
|
||||
if (value == default_font_variations)
|
||||
{
|
||||
g_string_append (string, "normal");
|
||||
return;
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, value->axes);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&coord))
|
||||
{
|
||||
if (first)
|
||||
first = FALSE;
|
||||
else
|
||||
g_string_append (string, ", ");
|
||||
g_string_append_printf (string, "\"%s\" ", name);
|
||||
_gtk_css_value_print (coord, string);
|
||||
}
|
||||
}
|
||||
|
||||
static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIATIONS = {
|
||||
gtk_css_value_font_variations_free,
|
||||
gtk_css_value_font_variations_compute,
|
||||
gtk_css_value_font_variations_equal,
|
||||
gtk_css_value_font_variations_transition,
|
||||
gtk_css_value_font_variations_print
|
||||
};
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_font_variations_value_new_empty (void)
|
||||
{
|
||||
GtkCssValue *result;
|
||||
|
||||
result = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_FONT_VARIATIONS);
|
||||
result->axes = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify) _gtk_css_value_unref);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
gtk_css_font_variations_value_new_default (void)
|
||||
{
|
||||
if (default_font_variations == NULL)
|
||||
default_font_variations = gtk_css_font_variations_value_new_empty ();
|
||||
|
||||
return _gtk_css_value_ref (default_font_variations);
|
||||
}
|
||||
|
||||
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_variations_value_parse (GtkCssParser *parser)
|
||||
{
|
||||
GtkCssValue *result, *coord;
|
||||
char *name;
|
||||
|
||||
if (_gtk_css_parser_try (parser, "normal", TRUE))
|
||||
return gtk_css_font_variations_value_new_default ();
|
||||
|
||||
result = gtk_css_font_variations_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;
|
||||
}
|
||||
|
||||
coord = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
|
||||
if (coord == NULL)
|
||||
{
|
||||
g_free (name);
|
||||
_gtk_css_value_unref (result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gtk_css_font_variations_value_add_axis (result, name, coord);
|
||||
g_free (name);
|
||||
} while (_gtk_css_parser_try (parser, ",", TRUE));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *
|
||||
gtk_css_font_variations_value_get_variations (GtkCssValue *value)
|
||||
{
|
||||
GtkCssValue *coord;
|
||||
GHashTableIter iter;
|
||||
gboolean first = TRUE;
|
||||
const char *name;
|
||||
GString *string;
|
||||
|
||||
g_return_val_if_fail (value->class == >K_CSS_VALUE_FONT_VARIATIONS, NULL);
|
||||
|
||||
if (value == default_font_variations)
|
||||
return NULL;
|
||||
|
||||
string = g_string_new ("");
|
||||
|
||||
g_hash_table_iter_init (&iter, value->axes);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&coord))
|
||||
{
|
||||
if (first)
|
||||
first = FALSE;
|
||||
else
|
||||
g_string_append (string, ",");
|
||||
g_string_append_printf (string, "%s=%g", name,
|
||||
_gtk_css_number_value_get (coord, 100));
|
||||
}
|
||||
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
36
gtk/gtkcssfontvariationsvalueprivate.h
Normal file
36
gtk/gtkcssfontvariationsvalueprivate.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_VARIATIONS_VALUE_PRIVATE_H__
|
||||
#define __GTK_CSS_FONT_VARIATIONS_PRIVATE_H__
|
||||
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * gtk_css_font_variations_value_new_default (void);
|
||||
|
||||
GtkCssValue * gtk_css_font_variations_value_parse (GtkCssParser *parser);
|
||||
|
||||
char * gtk_css_font_variations_value_get_variations (GtkCssValue *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_FONT_VARIATIONS_VALUE_PRIVATE_H__ */
|
@ -59,6 +59,7 @@
|
||||
#include "gtkcssshadowsvalueprivate.h"
|
||||
#include "gtkcssstringvalueprivate.h"
|
||||
#include "gtkcsstransformvalueprivate.h"
|
||||
#include "gtkcssfontvariationsvalueprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
/*** REGISTRATION ***/
|
||||
@ -664,6 +665,13 @@ parse_font_feature_settings (GtkCssStyleProperty *property,
|
||||
return gtk_css_font_features_value_parse (parser);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
parse_font_variation_settings (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
return gtk_css_font_variations_value_parse (parser);
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
box_shadow_value_parse (GtkCssStyleProperty *property,
|
||||
GtkCssParser *parser)
|
||||
@ -1816,4 +1824,12 @@ _gtk_css_style_property_init_properties (void)
|
||||
parse_font_feature_settings,
|
||||
NULL,
|
||||
gtk_css_font_features_value_new_default ());
|
||||
gtk_css_style_property_register ("font-variation-settings",
|
||||
GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS,
|
||||
G_TYPE_NONE,
|
||||
GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
|
||||
GTK_CSS_AFFECTS_TEXT_ATTRS | GTK_CSS_AFFECTS_TEXT_SIZE,
|
||||
parse_font_variation_settings,
|
||||
NULL,
|
||||
gtk_css_font_variations_value_new_default ());
|
||||
}
|
||||
|
@ -245,6 +245,7 @@ enum { /*< skip >*/
|
||||
GTK_CSS_PROPERTY_CARET_COLOR,
|
||||
GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR,
|
||||
GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS,
|
||||
GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS,
|
||||
/* add more */
|
||||
GTK_CSS_PROPERTY_N_PROPERTIES
|
||||
};
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include "gtkdebugupdatesprivate.h"
|
||||
#include "gsk/gskdebugprivate.h"
|
||||
#include "gtkeventcontrollerlegacyprivate.h"
|
||||
#include "gtkcssfontvariationsvalueprivate.h"
|
||||
|
||||
#include "inspector/window.h"
|
||||
|
||||
@ -8580,15 +8581,23 @@ update_pango_context (GtkWidget *widget,
|
||||
GtkStyleContext *style_context;
|
||||
GtkSettings *settings;
|
||||
cairo_font_options_t *font_options;
|
||||
GtkCssValue *value;
|
||||
char *variations;
|
||||
|
||||
style_context = _gtk_widget_get_style_context (widget);
|
||||
gtk_style_context_get (style_context,
|
||||
"font", &font_desc,
|
||||
NULL);
|
||||
|
||||
value = _gtk_style_context_peek_property (_gtk_widget_get_style_context (widget), GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS);
|
||||
variations = gtk_css_font_variations_value_get_variations (value);
|
||||
|
||||
pango_font_description_set_variations (font_desc, variations);
|
||||
|
||||
pango_context_set_font_description (context, font_desc);
|
||||
|
||||
pango_font_description_free (font_desc);
|
||||
g_free (variations);
|
||||
|
||||
pango_context_set_base_dir (context,
|
||||
_gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
|
||||
|
@ -88,6 +88,7 @@ gtk_public_sources = files([
|
||||
'gtkcssenumvalue.c',
|
||||
'gtkcssfiltervalue.c',
|
||||
'gtkcssfontfeaturesvalue.c',
|
||||
'gtkcssfontvariationsvalue.c',
|
||||
'gtkcssiconthemevalue.c',
|
||||
'gtkcssimage.c',
|
||||
'gtkcssimagebuiltin.c',
|
||||
|
Loading…
Reference in New Issue
Block a user