Merge branch 'css-line-decoration' into 'master'

textview: Apply line decoration from css

See merge request GNOME/gtk!3890
This commit is contained in:
Matthias Clasen
2021-08-27 01:37:57 +00:00
3 changed files with 176 additions and 84 deletions

View File

@@ -402,10 +402,10 @@ get_pango_underline_from_style (GtkTextDecorationStyle style)
g_return_val_if_reached (PANGO_UNDERLINE_SINGLE);
}
static PangoTextTransform
get_pango_text_transform_from_style (GtkTextTransform transform)
PangoTextTransform
gtk_css_style_get_pango_text_transform (GtkCssStyle *style)
{
switch (transform)
switch (_gtk_css_text_transform_value_get (style->font_variant->text_transform))
{
case GTK_CSS_TEXT_TRANSFORM_NONE:
return PANGO_TEXT_TRANSFORM_NONE;
@@ -451,77 +451,14 @@ append_separated (GString **s,
g_string_append (*s, text);
}
PangoAttrList *
gtk_css_style_get_pango_attributes (GtkCssStyle *style)
char *
gtk_css_style_compute_font_features (GtkCssStyle *style)
{
PangoAttrList *attrs = NULL;
GtkTextDecorationLine decoration_line;
GtkTextDecorationStyle decoration_style;
const GdkRGBA *color;
const GdkRGBA *decoration_color;
int letter_spacing;
GtkCssFontVariantLigature ligatures;
GtkCssFontVariantNumeric numeric;
GtkCssFontVariantEastAsian east_asian;
GString *s;
char *settings;
GtkTextTransform transform;
/* text-decoration */
decoration_line = _gtk_css_text_decoration_line_value_get (style->font_variant->text_decoration_line);
decoration_style = _gtk_css_text_decoration_style_value_get (style->font_variant->text_decoration_style);
color = gtk_css_color_value_get_rgba (style->core->color);
decoration_color = gtk_css_color_value_get_rgba (style->font_variant->text_decoration_color
? style->font_variant->text_decoration_color
: style->core->color);
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE)
{
attrs = add_pango_attr (attrs, pango_attr_underline_new (get_pango_underline_from_style (decoration_style)));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_underline_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_OVERLINE)
{
attrs = add_pango_attr (attrs, pango_attr_overline_new (get_pango_overline_from_style (decoration_style)));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_overline_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH)
{
attrs = add_pango_attr (attrs, pango_attr_strikethrough_new (TRUE));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_strikethrough_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
/* letter-spacing */
letter_spacing = _gtk_css_number_value_get (style->font->letter_spacing, 100);
if (letter_spacing != 0)
{
attrs = add_pango_attr (attrs, pango_attr_letter_spacing_new (letter_spacing * PANGO_SCALE));
}
/* line-height */
{
double height = gtk_css_line_height_value_get (style->font->line_height);
if (height != 0.0)
{
if (gtk_css_number_value_get_dimension (style->font->line_height) == GTK_CSS_DIMENSION_LENGTH)
attrs = add_pango_attr (attrs, pango_attr_line_height_new_absolute (height * PANGO_SCALE));
else
attrs = add_pango_attr (attrs, pango_attr_line_height_new (height));
}
}
/* OpenType features */
s = NULL;
GString *s = NULL;
switch (_gtk_css_font_kerning_value_get (style->font_variant->font_kerning))
{
@@ -671,15 +608,91 @@ gtk_css_style_get_pango_attributes (GtkCssStyle *style)
}
if (s)
return g_string_free (s, FALSE);
else
return NULL;
}
PangoAttrList *
gtk_css_style_get_pango_attributes (GtkCssStyle *style)
{
PangoAttrList *attrs = NULL;
GtkTextDecorationLine decoration_line;
GtkTextDecorationStyle decoration_style;
const GdkRGBA *color;
const GdkRGBA *decoration_color;
int letter_spacing;
/* text-decoration */
decoration_line = _gtk_css_text_decoration_line_value_get (style->font_variant->text_decoration_line);
decoration_style = _gtk_css_text_decoration_style_value_get (style->font_variant->text_decoration_style);
color = gtk_css_color_value_get_rgba (style->core->color);
decoration_color = gtk_css_color_value_get_rgba (style->font_variant->text_decoration_color
? style->font_variant->text_decoration_color
: style->core->color);
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE)
{
attrs = add_pango_attr (attrs, pango_attr_font_features_new (s->str));
g_string_free (s, TRUE);
attrs = add_pango_attr (attrs, pango_attr_underline_new (get_pango_underline_from_style (decoration_style)));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_underline_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_OVERLINE)
{
attrs = add_pango_attr (attrs, pango_attr_overline_new (get_pango_overline_from_style (decoration_style)));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_overline_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH)
{
attrs = add_pango_attr (attrs, pango_attr_strikethrough_new (TRUE));
if (!gdk_rgba_equal (color, decoration_color))
attrs = add_pango_attr (attrs, pango_attr_strikethrough_color_new (decoration_color->red * 65535. + 0.5,
decoration_color->green * 65535. + 0.5,
decoration_color->blue * 65535. + 0.5));
}
transform = _gtk_css_text_transform_value_get (style->font_variant->text_transform);
/* letter-spacing */
letter_spacing = _gtk_css_number_value_get (style->font->letter_spacing, 100);
if (letter_spacing != 0)
{
attrs = add_pango_attr (attrs, pango_attr_letter_spacing_new (letter_spacing * PANGO_SCALE));
}
if (transform != GTK_CSS_TEXT_TRANSFORM_NONE)
attrs = add_pango_attr (attrs, pango_attr_text_transform_new (get_pango_text_transform_from_style (transform)));
/* line-height */
{
double height = gtk_css_line_height_value_get (style->font->line_height);
if (height != 0.0)
{
if (gtk_css_number_value_get_dimension (style->font->line_height) == GTK_CSS_DIMENSION_LENGTH)
attrs = add_pango_attr (attrs, pango_attr_line_height_new_absolute (height * PANGO_SCALE));
else
attrs = add_pango_attr (attrs, pango_attr_line_height_new (height));
}
}
/* OpenType features */
{
char *font_features = gtk_css_style_compute_font_features (style);
if (font_features)
{
attrs = add_pango_attr (attrs, pango_attr_font_features_new (font_features));
g_free (font_features);
}
}
/* text-transform */
{
PangoTextTransform transform = gtk_css_style_get_pango_text_transform (style);
if (transform != PANGO_TEXT_TRANSFORM_NONE)
attrs = add_pango_attr (attrs, pango_attr_text_transform_new (transform));
}
return attrs;
}

View File

@@ -256,17 +256,18 @@ GtkCssValue * gtk_css_style_get_value (GtkCssStyle
GtkCssSection * gtk_css_style_get_section (GtkCssStyle *style,
guint id) G_GNUC_PURE;
gboolean gtk_css_style_is_static (GtkCssStyle *style) G_GNUC_PURE;
GtkCssStaticStyle * gtk_css_style_get_static_style (GtkCssStyle *style);
char * gtk_css_style_to_string (GtkCssStyle *style);
gboolean gtk_css_style_print (GtkCssStyle *style,
GString *string,
guint indent,
gboolean skip_initial);
PangoTextTransform gtk_css_style_get_pango_text_transform (GtkCssStyle *style);
char * gtk_css_style_compute_font_features (GtkCssStyle *style);
PangoAttrList * gtk_css_style_get_pango_attributes (GtkCssStyle *style);
PangoFontDescription * gtk_css_style_get_pango_font (GtkCssStyle *style);
GtkCssStaticStyle * gtk_css_style_get_static_style (GtkCssStyle *style);
GtkCssValues *gtk_css_values_new (GtkCssValuesType type);
GtkCssValues *gtk_css_values_ref (GtkCssValues *values);

View File

@@ -58,6 +58,8 @@
#include "gtkwidgetprivate.h"
#include "gtkjoinedmenuprivate.h"
#include "gtkcsslineheightvalueprivate.h"
#include "gtkcssenumvalueprivate.h"
/**
* GtkTextView:
@@ -4991,6 +4993,7 @@ gtk_text_view_css_changed (GtkWidget *widget,
if ((change == NULL ||
gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_TEXT |
GTK_CSS_AFFECTS_TEXT_ATTRS |
GTK_CSS_AFFECTS_BACKGROUND |
GTK_CSS_AFFECTS_CONTENT)) &&
priv->layout && priv->layout->default_style)
@@ -7641,7 +7644,9 @@ gtk_text_view_set_attributes_from_style (GtkTextView *text_view,
GtkCssStyle *style;
const GdkRGBA black = { 0, };
const GdkRGBA *color;
double height;
const GdkRGBA *decoration_color;
GtkTextDecorationLine decoration_line;
GtkTextDecorationStyle decoration_style;
if (!values->appearance.bg_rgba)
values->appearance.bg_rgba = gdk_rgba_copy (&black);
@@ -7660,19 +7665,92 @@ gtk_text_view_set_attributes_from_style (GtkTextView *text_view,
values->font = gtk_css_style_get_pango_font (style);
values->line_height = 0.0;
values->line_height_is_absolute = FALSE;
/* text-decoration */
height = gtk_css_line_height_value_get (style->font->line_height);
if (height != 0.0)
decoration_line = _gtk_css_text_decoration_line_value_get (style->font_variant->text_decoration_line);
decoration_style = _gtk_css_text_decoration_style_value_get (style->font_variant->text_decoration_style);
color = gtk_css_color_value_get_rgba (style->core->color);
decoration_color = gtk_css_color_value_get_rgba (style->font_variant->text_decoration_color
? style->font_variant->text_decoration_color
: style->core->color);
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_UNDERLINE)
{
switch (decoration_style)
{
case GTK_CSS_TEXT_DECORATION_STYLE_DOUBLE:
values->appearance.underline = PANGO_UNDERLINE_DOUBLE;
break;
case GTK_CSS_TEXT_DECORATION_STYLE_WAVY:
values->appearance.underline = PANGO_UNDERLINE_ERROR;
break;
case GTK_CSS_TEXT_DECORATION_STYLE_SOLID:
default:
values->appearance.underline = PANGO_UNDERLINE_SINGLE;
break;
}
if (values->appearance.underline_rgba)
*values->appearance.underline_rgba = *decoration_color;
else
values->appearance.underline_rgba = gdk_rgba_copy (decoration_color);
}
else
{
values->appearance.underline = PANGO_UNDERLINE_NONE;
gdk_rgba_free (values->appearance.underline_rgba);
values->appearance.underline_rgba = NULL;
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_OVERLINE)
{
values->appearance.overline = PANGO_OVERLINE_SINGLE;
if (values->appearance.overline_rgba)
*values->appearance.overline_rgba = *decoration_color;
else
values->appearance.overline_rgba = gdk_rgba_copy (decoration_color);
}
else
{
values->appearance.overline = PANGO_OVERLINE_NONE;
gdk_rgba_free (values->appearance.overline_rgba);
values->appearance.overline_rgba = NULL;
}
if (decoration_line & GTK_CSS_TEXT_DECORATION_LINE_LINE_THROUGH)
{
values->appearance.strikethrough = TRUE;
if (values->appearance.strikethrough_rgba)
*values->appearance.strikethrough_rgba = *decoration_color;
else
values->appearance.strikethrough_rgba = gdk_rgba_copy (decoration_color);
}
else
{
values->appearance.strikethrough = FALSE;
gdk_rgba_free (values->appearance.strikethrough_rgba);
values->appearance.strikethrough_rgba = NULL;
}
/* letter-spacing */
values->letter_spacing = _gtk_css_number_value_get (style->font->letter_spacing, 100) * PANGO_SCALE;
/* line-height */
values->line_height = gtk_css_line_height_value_get (style->font->line_height);
values->line_height_is_absolute = FALSE;
if (values->line_height != 0.0)
{
values->line_height = height;
if (gtk_css_number_value_get_dimension (style->font->line_height) == GTK_CSS_DIMENSION_LENGTH)
values->line_height_is_absolute = TRUE;
}
values->letter_spacing = _gtk_css_number_value_get (style->font->letter_spacing, 100) * PANGO_SCALE;
/* OpenType features */
g_free (values->font_features);
values->font_features = gtk_css_style_compute_font_features (style);
/* text-transform */
values->text_transform = gtk_css_style_get_pango_text_transform (style);
}
static void