texttag: Support overline and hyphenation control

Add support for recently added Pango attributes
for overlines and hyphenation control. The new
properties of GtkTextTag are
overline, overline-rgba, allow-breaks, show-spaces
and insert-hyphens.
This commit is contained in:
Matthias Clasen 2020-03-20 23:54:39 -04:00
parent 28e7a0a565
commit a8c6ae6085
4 changed files with 242 additions and 1 deletions

View File

@ -140,6 +140,9 @@ gtk_text_attributes_copy_values (GtkTextAttributes *src,
if (dest->appearance.underline_rgba)
gdk_rgba_free (dest->appearance.underline_rgba);
if (dest->appearance.overline_rgba)
gdk_rgba_free (dest->appearance.overline_rgba);
if (dest->appearance.strikethrough_rgba)
gdk_rgba_free (dest->appearance.strikethrough_rgba);
@ -171,6 +174,9 @@ gtk_text_attributes_copy_values (GtkTextAttributes *src,
if (src->appearance.underline_rgba)
dest->appearance.underline_rgba = gdk_rgba_copy (src->appearance.underline_rgba);
if (src->appearance.overline_rgba)
dest->appearance.overline_rgba = gdk_rgba_copy (src->appearance.overline_rgba);
if (src->appearance.strikethrough_rgba)
dest->appearance.strikethrough_rgba = gdk_rgba_copy (src->appearance.strikethrough_rgba);
@ -233,6 +239,9 @@ gtk_text_attributes_unref (GtkTextAttributes *values)
if (values->appearance.underline_rgba)
gdk_rgba_free (values->appearance.underline_rgba);
if (values->appearance.overline_rgba)
gdk_rgba_free (values->appearance.underline_rgba);
if (values->appearance.strikethrough_rgba)
gdk_rgba_free (values->appearance.strikethrough_rgba);
@ -300,6 +309,18 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
dest->appearance.underline_rgba = gdk_rgba_copy (vals->appearance.underline_rgba);
}
if (tag->priv->overline_rgba_set)
{
if (dest->appearance.overline_rgba)
{
gdk_rgba_free (dest->appearance.overline_rgba);
dest->appearance.overline_rgba = NULL;
}
if (vals->appearance.overline_rgba)
dest->appearance.overline_rgba = gdk_rgba_copy (vals->appearance.overline_rgba);
}
if (tag->priv->strikethrough_rgba_set)
{
if (dest->appearance.strikethrough_rgba)
@ -386,6 +407,9 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
if (tag->priv->underline_set)
dest->appearance.underline = vals->appearance.underline;
if (tag->priv->overline_set)
dest->appearance.overline = vals->appearance.overline;
if (tag->priv->strikethrough_set)
dest->appearance.strikethrough = vals->appearance.strikethrough;
@ -410,6 +434,15 @@ _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
if (tag->priv->font_features_set)
dest->font_features = g_strdup (vals->font_features);
if (tag->priv->allow_breaks_set)
dest->no_breaks = vals->no_breaks;
if (tag->priv->show_spaces_set)
dest->show_spaces = vals->show_spaces;
if (tag->priv->insert_hyphens_set)
dest->no_hyphens = vals->no_hyphens;
++n;
}
@ -435,6 +468,7 @@ _gtk_text_tag_affects_size (GtkTextTag *tag)
priv->pixels_inside_wrap_set ||
priv->tabs_set ||
priv->underline_set ||
priv->overline_set ||
priv->wrap_mode_set ||
priv->invisible_set ||
priv->font_features_set ||
@ -454,5 +488,7 @@ _gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
priv->pg_bg_color_set ||
priv->fallback_set ||
priv->underline_rgba_set ||
priv->strikethrough_rgba_set;
priv->overline_rgba_set ||
priv->strikethrough_rgba_set ||
priv->show_spaces_set;
}

View File

@ -87,12 +87,14 @@ struct _GtkTextAppearance
GdkRGBA *bg_rgba;
GdkRGBA *fg_rgba;
GdkRGBA *underline_rgba;
GdkRGBA *overline_rgba;
GdkRGBA *strikethrough_rgba;
/* super/subscript rise, can be negative */
gint rise;
guint underline : 4; /* PangoUnderline */
guint overline : 2; /* PangoOverline */
guint strikethrough : 1;
/* Whether to use background-related values; this is irrelevant for
@ -170,6 +172,10 @@ struct _GtkTextAttributes
guint bg_full_height : 1;
guint editable : 1;
guint no_fallback: 1;
guint no_breaks : 1;
guint show_spaces : 3; /* PangoShowFlags */
gint no_hyphens : 1;
GdkRGBA *pg_bg_rgba;

View File

@ -116,7 +116,9 @@ enum {
PROP_STRIKETHROUGH_RGBA,
PROP_RIGHT_MARGIN,
PROP_UNDERLINE,
PROP_OVERLINE,
PROP_UNDERLINE_RGBA,
PROP_OVERLINE_RGBA,
PROP_RISE,
PROP_BACKGROUND_FULL_HEIGHT,
PROP_LANGUAGE,
@ -127,6 +129,9 @@ enum {
PROP_FALLBACK,
PROP_LETTER_SPACING,
PROP_FONT_FEATURES,
PROP_ALLOW_BREAKS,
PROP_SHOW_SPACES,
PROP_INSERT_HYPHENS,
/* Behavior args */
PROP_ACCUMULATIVE_MARGIN,
@ -153,7 +158,9 @@ enum {
PROP_STRIKETHROUGH_RGBA_SET,
PROP_RIGHT_MARGIN_SET,
PROP_UNDERLINE_SET,
PROP_OVERLINE_SET,
PROP_UNDERLINE_RGBA_SET,
PROP_OVERLINE_RGBA_SET,
PROP_RISE_SET,
PROP_BACKGROUND_FULL_HEIGHT_SET,
PROP_LANGUAGE_SET,
@ -163,6 +170,9 @@ enum {
PROP_FALLBACK_SET,
PROP_LETTER_SPACING_SET,
PROP_FONT_FEATURES_SET,
PROP_ALLOW_BREAKS_SET,
PROP_SHOW_SPACES_SET,
PROP_INSERT_HYPHENS_SET,
LAST_ARG
};
@ -482,6 +492,15 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
PANGO_UNDERLINE_NONE,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_OVERLINE,
g_param_spec_enum ("overline",
P_("Overline"),
P_("Style of overline for this text"),
PANGO_TYPE_OVERLINE,
PANGO_OVERLINE_NONE,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:underline-rgba:
*
@ -500,6 +519,14 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
GDK_TYPE_RGBA,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_OVERLINE_RGBA,
g_param_spec_boxed ("overline-rgba",
P_("Overline RGBA"),
P_("Color of overline for this text"),
GDK_TYPE_RGBA,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:strikethrough-rgba:
*
@ -617,6 +644,31 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
NULL,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ALLOW_BREAKS,
g_param_spec_boolean ("allow-breaks",
P_("Allow Breaks"),
P_("Whether breaks are allowed."),
TRUE,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_SHOW_SPACES,
g_param_spec_flags ("show-spaces",
P_("Show spaces"),
P_("How to render invisible characters."),
PANGO_TYPE_SHOW_FLAGS,
PANGO_SHOW_NONE,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_INSERT_HYPHENS,
g_param_spec_boolean ("insert-hyphens",
P_("Insert hyphens"),
P_("Whether to insert hyphens at breaks."),
TRUE,
GTK_PARAM_READWRITE));
/**
* GtkTextTag:accumulative-margin:
*
@ -726,6 +778,10 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
P_("Underline set"),
P_("Whether this tag affects underlining"));
ADD_SET_PROP ("overline-set", PROP_OVERLINE_SET,
P_("Overline set"),
P_("Whether this tag affects overlining"));
/**
* GtkTextTag:underline-rgba-set:
*
@ -735,6 +791,10 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
P_("Underline RGBA set"),
P_("Whether this tag affects underlining color"));
ADD_SET_PROP ("overline-rgba-set", PROP_OVERLINE_RGBA_SET,
P_("Overline RGBA set"),
P_("Whether this tag affects overlining color"));
/**
* GtkTextTag:strikethrough-rgba-set:
*
@ -771,6 +831,18 @@ gtk_text_tag_class_init (GtkTextTagClass *klass)
ADD_SET_PROP ("font-features-set", PROP_FONT_FEATURES_SET,
P_("Font features set"),
P_("Whether this tag affects font features"));
ADD_SET_PROP ("allow-breaks-set", PROP_ALLOW_BREAKS_SET,
P_("Allow breaks set"),
P_("Whether this tag affects line breaks"));
ADD_SET_PROP ("show-spaces-set", PROP_SHOW_SPACES_SET,
P_("Show spaces set"),
P_("Whether this tag affects rendering of invisible characters"));
ADD_SET_PROP ("insert-hyphens-set", PROP_INSERT_HYPHENS_SET,
P_("Insert hyphens set"),
P_("Whether this tag affects insertion of hyphens"));
}
static void
@ -849,6 +921,36 @@ set_underline_rgba (GtkTextTag *tag,
}
}
static void
set_overline_rgba (GtkTextTag *tag,
const GdkRGBA *rgba)
{
GtkTextTagPrivate *priv = tag->priv;
if (priv->values->appearance.overline_rgba)
gdk_rgba_free (priv->values->appearance.overline_rgba);
priv->values->appearance.overline_rgba = NULL;
if (rgba)
{
priv->values->appearance.overline_rgba = gdk_rgba_copy (rgba);
if (!priv->overline_rgba_set)
{
priv->overline_rgba_set = TRUE;
g_object_notify (G_OBJECT (tag), "overline-rgba-set");
}
}
else
{
if (priv->overline_rgba_set)
{
priv->overline_rgba_set = FALSE;
g_object_notify (G_OBJECT (tag), "overline-rgba-set");
}
}
}
static void
set_strikethrough_rgba (GtkTextTag *tag,
const GdkRGBA *rgba)
@ -1366,6 +1468,12 @@ gtk_text_tag_set_property (GObject *object,
g_object_notify (object, "underline-set");
break;
case PROP_OVERLINE:
priv->overline_set = TRUE;
priv->values->appearance.overline = g_value_get_enum (value);
g_object_notify (object, "overline-set");
break;
case PROP_UNDERLINE_RGBA:
{
GdkRGBA *color = g_value_get_boxed (value);
@ -1373,6 +1481,13 @@ gtk_text_tag_set_property (GObject *object,
}
break;
case PROP_OVERLINE_RGBA:
{
GdkRGBA *color = g_value_get_boxed (value);
set_overline_rgba (text_tag, color);
}
break;
case PROP_RISE:
priv->rise_set = TRUE;
priv->values->appearance.rise = g_value_get_int (value);
@ -1453,6 +1568,24 @@ gtk_text_tag_set_property (GObject *object,
g_object_notify (object, "font-features-set");
break;
case PROP_ALLOW_BREAKS:
priv->allow_breaks_set = TRUE;
priv->values->no_breaks = !g_value_get_boolean (value);
g_object_notify (object, "allow-breaks-set");
break;
case PROP_SHOW_SPACES:
priv->show_spaces_set = TRUE;
priv->values->show_spaces = g_value_get_flags (value);
g_object_notify (object, "show-spaces-set");
break;
case PROP_INSERT_HYPHENS:
priv->insert_hyphens_set = TRUE;
priv->values->no_hyphens = !g_value_get_boolean (value);
g_object_notify (object, "insert-hyphens-set");
break;
case PROP_ACCUMULATIVE_MARGIN:
priv->accumulative_margin = g_value_get_boolean (value);
g_object_notify (object, "accumulative-margin");
@ -1553,10 +1686,18 @@ gtk_text_tag_set_property (GObject *object,
priv->underline_set = g_value_get_boolean (value);
break;
case PROP_OVERLINE_SET:
priv->overline_set = g_value_get_boolean (value);
break;
case PROP_UNDERLINE_RGBA_SET:
priv->underline_rgba_set = g_value_get_boolean (value);
break;
case PROP_OVERLINE_RGBA_SET:
priv->overline_rgba_set = g_value_get_boolean (value);
break;
case PROP_RISE_SET:
priv->rise_set = g_value_get_boolean (value);
size_changed = TRUE;
@ -1597,6 +1738,18 @@ gtk_text_tag_set_property (GObject *object,
priv->font_features_set = g_value_get_boolean (value);
break;
case PROP_ALLOW_BREAKS_SET:
priv->allow_breaks_set = g_value_get_boolean (value);
break;
case PROP_SHOW_SPACES_SET:
priv->show_spaces_set = g_value_get_boolean (value);
break;
case PROP_INSERT_HYPHENS_SET:
priv->insert_hyphens_set = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1741,11 +1894,20 @@ gtk_text_tag_get_property (GObject *object,
g_value_set_enum (value, priv->values->appearance.underline);
break;
case PROP_OVERLINE:
g_value_set_enum (value, priv->values->appearance.overline);
break;
case PROP_UNDERLINE_RGBA:
if (priv->underline_rgba_set)
g_value_set_boxed (value, priv->values->appearance.underline_rgba);
break;
case PROP_OVERLINE_RGBA:
if (priv->overline_rgba_set)
g_value_set_boxed (value, priv->values->appearance.overline_rgba);
break;
case PROP_RISE:
g_value_set_int (value, priv->values->appearance.rise);
break;
@ -1784,6 +1946,18 @@ gtk_text_tag_get_property (GObject *object,
g_value_set_string (value, priv->values->font_features);
break;
case PROP_ALLOW_BREAKS:
g_value_set_boolean (value, !priv->values->no_breaks);
break;
case PROP_SHOW_SPACES:
g_value_set_flags (value, priv->values->show_spaces);
break;
case PROP_INSERT_HYPHENS:
g_value_set_boolean (value, !priv->values->no_hyphens);
break;
case PROP_ACCUMULATIVE_MARGIN:
g_value_set_boolean (value, priv->accumulative_margin);
break;
@ -1862,10 +2036,18 @@ gtk_text_tag_get_property (GObject *object,
g_value_set_boolean (value, priv->underline_set);
break;
case PROP_OVERLINE_SET:
g_value_set_boolean (value, priv->overline_set);
break;
case PROP_UNDERLINE_RGBA_SET:
g_value_set_boolean (value, priv->underline_rgba_set);
break;
case PROP_OVERLINE_RGBA_SET:
g_value_set_boolean (value, priv->overline_rgba_set);
break;
case PROP_RISE_SET:
g_value_set_boolean (value, priv->rise_set);
break;
@ -1902,6 +2084,18 @@ gtk_text_tag_get_property (GObject *object,
g_value_set_boolean (value, priv->font_features_set);
break;
case PROP_ALLOW_BREAKS_SET:
g_value_set_boolean (value, priv->allow_breaks_set);
break;
case PROP_SHOW_SPACES_SET:
g_value_set_boolean (value, priv->show_spaces_set);
break;
case PROP_INSERT_HYPHENS_SET:
g_value_set_boolean (value, priv->insert_hyphens_set);
break;
case PROP_BACKGROUND:
case PROP_FOREGROUND:
case PROP_PARAGRAPH_BACKGROUND:

View File

@ -59,6 +59,7 @@ struct _GtkTextTagPrivate
guint bg_color_set : 1;
guint fg_color_set : 1;
guint underline_rgba_set : 1;
guint overline_rgba_set : 1;
guint strikethrough_rgba_set : 1;
guint scale_set : 1;
guint justification_set : 1;
@ -72,6 +73,7 @@ struct _GtkTextTagPrivate
guint pixels_inside_wrap_set : 1;
guint tabs_set : 1;
guint underline_set : 1;
guint overline_set : 1;
guint wrap_mode_set : 1;
guint bg_full_height_set : 1;
guint invisible_set : 1;
@ -81,6 +83,9 @@ struct _GtkTextTagPrivate
guint fallback_set : 1;
guint letter_spacing_set : 1;
guint font_features_set : 1;
guint allow_breaks_set : 1;
guint show_spaces_set : 1;
guint insert_hyphens_set : 1;
/* Whether these margins accumulate or override */
guint accumulative_margin : 1;