diff --git a/gtk/gtkcssanimatedstyle.c b/gtk/gtkcssanimatedstyle.c index 52e0cabc3b..eb62780360 100644 --- a/gtk/gtkcssanimatedstyle.c +++ b/gtk/gtkcssanimatedstyle.c @@ -204,6 +204,10 @@ gtk_css_animated_style_set_animated_value (GtkCssAnimatedStyle *animated, unshare_font (animated); gtk_css_take_value (&style->font->letter_spacing, value); break; + case GTK_CSS_PROPERTY_LINE_HEIGHT: + unshare_font (animated); + gtk_css_take_value (&style->font->line_height, value); + break; case GTK_CSS_PROPERTY_TEXT_DECORATION_LINE: unshare_font_variant (animated); gtk_css_take_value (&style->font_variant->text_decoration_line, value); diff --git a/gtk/gtkcsslineheightvalue.c b/gtk/gtkcsslineheightvalue.c new file mode 100644 index 0000000000..c9104cee24 --- /dev/null +++ b/gtk/gtkcsslineheightvalue.c @@ -0,0 +1,184 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2021 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 . + */ + +#include "config.h" + +#include "gtkcsslineheightvalueprivate.h" +#include "gtkcssnumbervalueprivate.h" +#include "gtkcssstyleprivate.h" + +struct _GtkCssValue { + GTK_CSS_VALUE_BASE + GtkCssValue *height; +}; + +static GtkCssValue *default_line_height; + +static GtkCssValue *gtk_css_value_line_height_new_empty (void); +static GtkCssValue *gtk_css_value_line_height_new (GtkCssValue *height); + +static void +gtk_css_value_line_height_free (GtkCssValue *value) +{ + _gtk_css_value_unref (value->height); + g_slice_free (GtkCssValue, value); +} + +static GtkCssValue * +gtk_css_value_line_height_compute (GtkCssValue *value, + guint property_id, + GtkStyleProvider *provider, + GtkCssStyle *style, + GtkCssStyle *parent_style) +{ + GtkCssValue *height; + + height = _gtk_css_value_compute (value->height, property_id, provider, style, parent_style); + + if (gtk_css_number_value_get_dimension (height) == GTK_CSS_DIMENSION_PERCENTAGE) + { + double factor; + GtkCssValue *val; + GtkCssValue *computed; + + factor = _gtk_css_number_value_get (height, 1); + val = gtk_css_dimension_value_new (factor, GTK_CSS_EM); + + computed = _gtk_css_value_compute (val, + GTK_CSS_PROPERTY_FONT_SIZE, + provider, + style, + parent_style); + + _gtk_css_value_unref (val); + _gtk_css_value_unref (height); + + return computed; + } + else + { + return height; + } +} + +static gboolean +gtk_css_value_line_height_equal (const GtkCssValue *value1, + const GtkCssValue *value2) +{ + if (value1->height == NULL || value2->height == NULL) + return FALSE; + + return _gtk_css_value_equal (value1->height, value2->height); +} + +static GtkCssValue * +gtk_css_value_line_height_transition (GtkCssValue *start, + GtkCssValue *end, + guint property_id, + double progress) +{ + GtkCssValue *height; + + if (start->height == NULL || end->height == NULL) + return NULL; + + height = _gtk_css_value_transition (start->height, end->height, property_id, progress); + if (height == NULL) + return NULL; + + return gtk_css_value_line_height_new (height); +} + +static void +gtk_css_value_line_height_print (const GtkCssValue *value, + GString *string) +{ + if (value->height == NULL) + g_string_append (string, "normal"); + else + _gtk_css_value_print (value->height, string); +} + +static const GtkCssValueClass GTK_CSS_VALUE_LINE_HEIGHT = { + "GtkCssLineHeightValue", + gtk_css_value_line_height_free, + gtk_css_value_line_height_compute, + gtk_css_value_line_height_equal, + gtk_css_value_line_height_transition, + NULL, + NULL, + gtk_css_value_line_height_print +}; + +static GtkCssValue * +gtk_css_value_line_height_new_empty (void) +{ + GtkCssValue *result; + + result = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_LINE_HEIGHT); + result->height = NULL; + result->is_computed = TRUE; + + return result; +} + +static GtkCssValue * +gtk_css_value_line_height_new (GtkCssValue *height) +{ + GtkCssValue *result; + + result = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_LINE_HEIGHT); + result->height = height; + + return result; +} + +GtkCssValue * +gtk_css_line_height_value_get_default (void) +{ + if (default_line_height == NULL) + default_line_height = gtk_css_value_line_height_new_empty (); + + return default_line_height; +} + +GtkCssValue * +gtk_css_line_height_value_parse (GtkCssParser *parser) +{ + GtkCssValue *height; + + if (gtk_css_parser_try_ident (parser, "normal")) + return _gtk_css_value_ref (gtk_css_line_height_value_get_default ()); + + height = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | + GTK_CSS_PARSE_PERCENT | + GTK_CSS_PARSE_LENGTH | + GTK_CSS_POSITIVE_ONLY); + if (!height) + return NULL; + + return gtk_css_value_line_height_new (height); +} + +double +gtk_css_line_height_value_get (const GtkCssValue *value) +{ + if (value->class == >K_CSS_VALUE_LINE_HEIGHT) + return 0.0; + + return _gtk_css_number_value_get (value, 1); +} diff --git a/gtk/gtkcsslineheightvalueprivate.h b/gtk/gtkcsslineheightvalueprivate.h new file mode 100644 index 0000000000..6703637fb9 --- /dev/null +++ b/gtk/gtkcsslineheightvalueprivate.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2021 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 . + * + * Authors: Matthias Clasen + */ + +#ifndef __GTK_CSS_LINE_HEIGHT_VALUE_PRIVATE_H__ +#define __GTK_CSS_LINE_HEIGHT_VALUE_PRIVATE_H__ + +#include +#include "gtk/css/gtkcsstokenizerprivate.h" +#include "gtk/css/gtkcssparserprivate.h" +#include "gtkcssvalueprivate.h" + +G_BEGIN_DECLS + +GtkCssValue * gtk_css_line_height_value_get_default (void); +GtkCssValue * gtk_css_line_height_value_parse (GtkCssParser *parser); + +double gtk_css_line_height_value_get (const GtkCssValue *value); + +G_END_DECLS + +#endif /* __GTK_CSS_LINE_HEIGHT_VALUE_PRIVATE_H__ */ diff --git a/gtk/gtkcssstaticstyle.c b/gtk/gtkcssstaticstyle.c index 1c8dd80c56..ad906431d8 100644 --- a/gtk/gtkcssstaticstyle.c +++ b/gtk/gtkcssstaticstyle.c @@ -107,11 +107,12 @@ static const int font_props[] = { GTK_CSS_PROPERTY_FONT_WEIGHT, GTK_CSS_PROPERTY_FONT_STRETCH, GTK_CSS_PROPERTY_LETTER_SPACING, - GTK_CSS_PROPERTY_TEXT_SHADOW, + GTK_CSS_PROPERTY_TEXT_SHADOW, GTK_CSS_PROPERTY_CARET_COLOR, GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR, GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS, GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS, + GTK_CSS_PROPERTY_LINE_HEIGHT, }; static const int font_variant_props[] = { GTK_CSS_PROPERTY_TEXT_DECORATION_LINE, @@ -417,6 +418,9 @@ gtk_css_static_style_set_value (GtkCssStaticStyle *sstyle, case GTK_CSS_PROPERTY_LETTER_SPACING: gtk_css_take_value (&style->font->letter_spacing, value); break; + case GTK_CSS_PROPERTY_LINE_HEIGHT: + gtk_css_take_value (&style->font->line_height, value); + break; case GTK_CSS_PROPERTY_TEXT_DECORATION_LINE: gtk_css_take_value (&style->font_variant->text_decoration_line, value); break; diff --git a/gtk/gtkcssstyle.c b/gtk/gtkcssstyle.c index 0f890a005d..54aa0e7d23 100644 --- a/gtk/gtkcssstyle.c +++ b/gtk/gtkcssstyle.c @@ -117,6 +117,8 @@ gtk_css_style_get_value (GtkCssStyle *style, return style->font->font_stretch; case GTK_CSS_PROPERTY_LETTER_SPACING: return style->font->letter_spacing; + case GTK_CSS_PROPERTY_LINE_HEIGHT: + return style->font->line_height; case GTK_CSS_PROPERTY_TEXT_DECORATION_LINE: return style->font_variant->text_decoration_line; case GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR: diff --git a/gtk/gtkcssstyle.h b/gtk/gtkcssstyle.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gtk/gtkcssstyleprivate.h b/gtk/gtkcssstyleprivate.h index 27666e9978..5a78d3d962 100644 --- a/gtk/gtkcssstyleprivate.h +++ b/gtk/gtkcssstyleprivate.h @@ -151,6 +151,7 @@ struct _GtkCssFontValues { GtkCssValue *secondary_caret_color; // NULL if currentColor GtkCssValue *font_feature_settings; GtkCssValue *font_variation_settings; + GtkCssValue *line_height; }; struct _GtkCssFontVariantValues { diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c index 6df32116a8..a98573c69f 100644 --- a/gtk/gtkcssstylepropertyimpl.c +++ b/gtk/gtkcssstylepropertyimpl.c @@ -52,6 +52,7 @@ #include "gtkcssstringvalueprivate.h" #include "gtkcsstransformvalueprivate.h" #include "gtkcssfontvariationsvalueprivate.h" +#include "gtkcsslineheightvalueprivate.h" #include "gtktypebuiltins.h" /*** REGISTRATION ***/ @@ -812,6 +813,13 @@ transform_origin_parse (GtkCssStyleProperty *property, return _gtk_css_position_value_parse (parser); } +static GtkCssValue * +parse_line_height (GtkCssStyleProperty *property, + GtkCssParser *parser) +{ + return gtk_css_line_height_value_parse (parser); +} + /*** REGISTRATION ***/ G_STATIC_ASSERT (GTK_CSS_PROPERTY_COLOR == 0); @@ -1401,4 +1409,10 @@ _gtk_css_style_property_init_properties (void) GTK_CSS_AFFECTS_TEXT_ATTRS | GTK_CSS_AFFECTS_TEXT_SIZE, parse_font_variation_settings, gtk_css_font_variations_value_new_default ()); + gtk_css_style_property_register ("line-height", + GTK_CSS_PROPERTY_LINE_HEIGHT, + GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED, + GTK_CSS_AFFECTS_TEXT_ATTRS | GTK_CSS_AFFECTS_TEXT_SIZE, + parse_line_height, + _gtk_css_value_ref (gtk_css_line_height_value_get_default ())); } diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h index 35ae56a41c..1a2320a6bb 100644 --- a/gtk/gtkcsstypesprivate.h +++ b/gtk/gtkcsstypesprivate.h @@ -275,6 +275,7 @@ enum { /*< skip >*/ GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR, GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS, GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS, + GTK_CSS_PROPERTY_LINE_HEIGHT, /* add more */ GTK_CSS_PROPERTY_N_PROPERTIES }; diff --git a/gtk/meson.build b/gtk/meson.build index 18fbe6ac61..fa66764c50 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -78,6 +78,7 @@ gtk_private_sources = files([ 'gtkcssinheritvalue.c', 'gtkcssinitialvalue.c', 'gtkcsskeyframes.c', + 'gtkcsslineheightvalue.c', 'gtkcsslookup.c', 'gtkcssnode.c', 'gtkcssnodedeclaration.c',