From 3bd01215723f0c0de9339418c5de762d476b79a4 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 7 Feb 2022 01:17:08 -0500 Subject: Make strikethrough styled Support single and double styles for strikethrough. --- pango/pango-attr-list.c | 3 ++- pango/pango-attributes.c | 6 ++--- pango/pango-attributes.h | 7 ++--- pango/pango-layout.c | 14 +++++----- pango/pango-markup.c | 26 ++++++++++++++----- pango/pango-renderer.c | 66 +++++++++++++++++++++++++++++++++--------------- pango/pango-renderer.h | 2 +- pango/serializer.c | 3 ++- 8 files changed, 85 insertions(+), 42 deletions(-) diff --git a/pango/pango-attr-list.c b/pango/pango-attr-list.c index 8f31971a..505963f2 100644 --- a/pango/pango-attr-list.c +++ b/pango/pango-attr-list.c @@ -766,6 +766,7 @@ get_attr_value_type (PangoAttrType type) case PANGO_ATTR_GRAVITY: return PANGO_TYPE_GRAVITY; case PANGO_ATTR_GRAVITY_HINT: return PANGO_TYPE_GRAVITY_HINT; case PANGO_ATTR_UNDERLINE: return PANGO_TYPE_LINE_STYLE; + case PANGO_ATTR_STRIKETHROUGH: return PANGO_TYPE_LINE_STYLE; case PANGO_ATTR_OVERLINE: return PANGO_TYPE_OVERLINE; case PANGO_ATTR_BASELINE_SHIFT: return PANGO_TYPE_BASELINE_SHIFT; case PANGO_ATTR_FONT_SCALE: return PANGO_TYPE_FONT_SCALE; @@ -1143,7 +1144,7 @@ pango_attr_list_from_string (const char *text) break; case PANGO_ATTR_STRIKETHROUGH: - BOOLEAN_ATTR(strikethrough, gboolean); + ENUM_ATTR(strikethrough, PangoLineStyle, PANGO_LINE_STYLE_NONE, PANGO_LINE_STYLE_DOTTED); break; case PANGO_ATTR_RISE: diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 7fcf47e0..1e305229 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -367,7 +367,7 @@ pango_attr_underline_position_new (PangoUnderlinePosition position) } /** * pango_attr_strikethrough_new: - * @strikethrough: %TRUE if the text should be struck-through + * @style: the line style * * Create a new strike-through attribute. * @@ -376,9 +376,9 @@ pango_attr_underline_position_new (PangoUnderlinePosition position) * [method@Pango.Attribute.destroy] */ PangoAttribute * -pango_attr_strikethrough_new (gboolean strikethrough) +pango_attr_strikethrough_new (PangoLineStyle style) { - return pango_attr_boolean_new (PANGO_ATTR_STRIKETHROUGH, (int)strikethrough); + return pango_attr_int_new (PANGO_ATTR_STRIKETHROUGH, (int)style); } /** diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index bf309c08..b9b82632 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -42,7 +42,8 @@ G_BEGIN_DECLS * @PANGO_ATTR_FONT_DESC: font description * @PANGO_ATTR_FOREGROUND: foreground color * @PANGO_ATTR_BACKGROUND: background color - * @PANGO_ATTR_UNDERLINE: whether the text has an underline + * @PANGO_ATTR_UNDERLINE: underline style + * @PANGO_ATTR_UNDERLINE_POSITION: underline position * @PANGO_ATTR_STRIKETHROUGH: whether the text is struck-through * @PANGO_ATTR_RISE: baseline displacement * @PANGO_ATTR_SCALE: font size scale factor @@ -89,7 +90,7 @@ typedef enum PANGO_ATTR_BACKGROUND = PANGO_ATTR_TYPE (COLOR, RENDERING, OVERRIDES), PANGO_ATTR_UNDERLINE = PANGO_ATTR_TYPE (INT, RENDERING, OVERRIDES), PANGO_ATTR_UNDERLINE_POSITION = PANGO_ATTR_TYPE (INT, RENDERING, OVERRIDES), - PANGO_ATTR_STRIKETHROUGH = PANGO_ATTR_TYPE (BOOLEAN, RENDERING, OVERRIDES), + PANGO_ATTR_STRIKETHROUGH = PANGO_ATTR_TYPE (INT, RENDERING, OVERRIDES), PANGO_ATTR_RISE = PANGO_ATTR_TYPE (INT, ITEMIZATION, OVERRIDES), PANGO_ATTR_SCALE = PANGO_ATTR_TYPE (FLOAT, ITEMIZATION, OVERRIDES), PANGO_ATTR_FALLBACK = PANGO_ATTR_TYPE (BOOLEAN, ITEMIZATION, OVERRIDES), @@ -174,7 +175,7 @@ PANGO_AVAILABLE_IN_1_52 PangoAttribute * pango_attr_underline_position_new (PangoUnderlinePosition position); PANGO_AVAILABLE_IN_ALL -PangoAttribute * pango_attr_strikethrough_new (gboolean strikethrough); +PangoAttribute * pango_attr_strikethrough_new (PangoLineStyle style); PANGO_AVAILABLE_IN_1_8 PangoAttribute * pango_attr_strikethrough_color_new (PangoColor *color); PANGO_AVAILABLE_IN_ALL diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 848afab9..cd9d2174 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -108,7 +108,7 @@ struct _ItemProperties { PangoLineStyle uline_style; PangoUnderlinePosition uline_position; - guint strikethrough : 1; + PangoLineStyle strikethrough_style; guint oline_single : 1; guint showing_space : 1; gint letter_spacing; @@ -5551,6 +5551,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, ItemProperties properties; PangoFontMetrics *metrics = NULL; gboolean has_underline; + gboolean has_strikethrough; gboolean has_overline; int y_offset; @@ -5561,11 +5562,12 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, has_underline = properties.uline_style != PANGO_LINE_STYLE_NONE; has_overline = properties.oline_single; + has_strikethrough = properties.strikethrough_style != PANGO_LINE_STYLE_NONE; if (!run_logical && (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)) run_logical = &logical; - if (!run_logical && (has_underline || has_overline || properties.strikethrough)) + if (!run_logical && (has_underline || has_overline || has_strikethrough)) run_logical = &logical; if (!run_logical && line_logical) @@ -5574,7 +5576,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, pango_glyph_string_extents (run->glyphs, run->item->analysis.font, run_ink, run_logical); - if (run_ink && (has_underline || has_overline || properties.strikethrough)) + if (run_ink && (has_underline || has_overline || has_strikethrough)) { int underline_thickness; int underline_position; @@ -5602,7 +5604,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, * If run_ink->height == 0, we should adjust run_ink->y appropriately. */ - if (properties.strikethrough) + if (has_strikethrough) { if (run_ink->height == 0) { @@ -6728,8 +6730,8 @@ pango_layout_get_item_properties (PangoItem *item, properties->uline_style = PANGO_LINE_STYLE_NONE; properties->uline_position = PANGO_UNDERLINE_POSITION_NORMAL; + properties->strikethrough_style = PANGO_LINE_STYLE_NONE; properties->oline_single = FALSE; - properties->strikethrough = FALSE; properties->showing_space = FALSE; properties->letter_spacing = 0; properties->line_height = 0.0; @@ -6762,7 +6764,7 @@ pango_layout_get_item_properties (PangoItem *item, break; case PANGO_ATTR_STRIKETHROUGH: - properties->strikethrough = attr->int_value; + properties->strikethrough_style = attr->int_value; break; case PANGO_ATTR_LETTER_SPACING: diff --git a/pango/pango-markup.c b/pango/pango-markup.c index 3802fa5e..b2da8e49 100644 --- a/pango/pango-markup.c +++ b/pango/pango-markup.c @@ -1218,6 +1218,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, const char *foreground = NULL; const char *background = NULL; const char *underline = NULL; + const char *underline_position = NULL; const char *underline_color = NULL; const char *overline = NULL; const char *overline_color = NULL; @@ -1332,6 +1333,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, break; case 'u': CHECK_ATTRIBUTE (underline); + CHECK_ATTRIBUTE (underline_position); CHECK_ATTRIBUTE (underline_color); break; case 'r': @@ -1546,12 +1548,22 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, if (G_UNLIKELY (underline)) { - PangoLineStyle ul = PANGO_LINE_STYLE_NONE; + PangoLineStyle style = PANGO_LINE_STYLE_NONE; - if (!span_parse_enum ("underline", underline, PANGO_TYPE_LINE_STYLE, (int*)(void*)&ul, line_number, error)) + if (!span_parse_enum ("underline", underline, PANGO_TYPE_LINE_STYLE, (int*)(void*)&style, line_number, error)) goto error; - add_attribute (tag, pango_attr_underline_new (ul)); + add_attribute (tag, pango_attr_underline_new (style)); + } + + if (G_UNLIKELY (underline_position)) + { + PangoUnderlinePosition pos = PANGO_UNDERLINE_POSITION_NORMAL; + + if (!span_parse_enum ("underline_position", underline_position, PANGO_TYPE_UNDERLINE_POSITION, (int*)(void*)&pos, line_number, error)) + goto error; + + add_attribute (tag, pango_attr_underline_position_new (pos)); } if (G_UNLIKELY (underline_color)) @@ -1619,12 +1631,12 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, if (G_UNLIKELY (strikethrough)) { - gboolean b = FALSE; + PangoLineStyle style = PANGO_LINE_STYLE_NONE; - if (!span_parse_boolean ("strikethrough", strikethrough, &b, line_number, error)) - goto error; + if (!span_parse_enum ("strikethrough", strikethrough, PANGO_TYPE_LINE_STYLE, (int*)(void*)&style, line_number, error)) + goto error; - add_attribute (tag, pango_attr_strikethrough_new (b)); + add_attribute (tag, pango_attr_strikethrough_new (style)); } if (G_UNLIKELY (strikethrough_color)) diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c index a246bb73..9fb10a42 100644 --- a/pango/pango-renderer.c +++ b/pango/pango-renderer.c @@ -45,7 +45,7 @@ struct _LineState PangoUnderlinePosition underline_position; PangoRectangle underline_rect; - gboolean strikethrough; + PangoLineStyle strikethrough; PangoRectangle strikethrough_rect; int strikethrough_glyphs; @@ -284,17 +284,40 @@ draw_strikethrough (PangoRenderer *renderer, LineState *state) { PangoRectangle *rect = &state->strikethrough_rect; - int num_glyphs = state->strikethrough_glyphs; - if (state->strikethrough && num_glyphs > 0) - pango_renderer_draw_rectangle (renderer, - PANGO_RENDER_PART_STRIKETHROUGH, - rect->x, - rect->y / num_glyphs, - rect->width, - rect->height / num_glyphs); + if (state->strikethrough_glyphs > 0) + { + rect->y /= state->strikethrough_glyphs; + rect->height /= state->strikethrough_glyphs; + + switch (state->strikethrough) + { + case PANGO_LINE_STYLE_NONE: + break; + case PANGO_LINE_STYLE_DOUBLE: + pango_renderer_draw_rectangle (renderer, + PANGO_RENDER_PART_STRIKETHROUGH, + rect->x, + rect->y - rect->height, + rect->width, + rect->height); + rect->y += rect->height; + G_GNUC_FALLTHROUGH; + case PANGO_LINE_STYLE_SINGLE: + case PANGO_LINE_STYLE_DOTTED: + pango_renderer_draw_rectangle (renderer, + PANGO_RENDER_PART_STRIKETHROUGH, + rect->x, + rect->y, + rect->width, + rect->height); + break; + default: + break; + } + } - state->strikethrough = FALSE; + state->strikethrough = PANGO_LINE_STYLE_NONE; state->strikethrough_glyphs = 0; rect->x += rect->width; rect->width = 0; @@ -336,7 +359,7 @@ handle_line_state_change (PangoRenderer *renderer, } if (part == PANGO_RENDER_PART_STRIKETHROUGH && - state->strikethrough) + state->strikethrough != PANGO_LINE_STYLE_NONE) { PangoRectangle *rect = &state->strikethrough_rect; @@ -372,7 +395,7 @@ add_underline (PangoRenderer *renderer, g_assert_not_reached (); break; case PANGO_LINE_STYLE_SINGLE: - if (state->underline_position == PANGO_UNDERLINE_POSITION_UNDER) + if (renderer->underline_position == PANGO_UNDERLINE_POSITION_UNDER) { new_rect.y += ink_rect->y + ink_rect->height + underline_thickness; break; @@ -484,7 +507,7 @@ add_strikethrough (PangoRenderer *renderer, new_rect.y = (base_y - strikethrough_position) * num_glyphs; new_rect.height = strikethrough_thickness * num_glyphs; - if (state->strikethrough) + if (state->strikethrough == renderer->strikethrough) { current_rect->width = new_rect.x + new_rect.width - current_rect->x; current_rect->y += new_rect.y; @@ -493,8 +516,10 @@ add_strikethrough (PangoRenderer *renderer, } else { + draw_strikethrough (renderer, state); + *current_rect = new_rect; - state->strikethrough = TRUE; + state->strikethrough = renderer->strikethrough; state->strikethrough_glyphs = num_glyphs; } } @@ -550,7 +575,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, state.underline = PANGO_LINE_STYLE_NONE; state.underline_position = PANGO_UNDERLINE_POSITION_NORMAL; state.overline = PANGO_OVERLINE_NONE; - state.strikethrough = FALSE; + state.strikethrough = PANGO_LINE_STYLE_NONE; text = G_LIKELY (line->layout) ? pango_layout_get_text (line->layout) : NULL; @@ -569,7 +594,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, if (renderer->underline != PANGO_LINE_STYLE_NONE || renderer->priv->overline != PANGO_OVERLINE_NONE || - renderer->strikethrough) + renderer->strikethrough != PANGO_LINE_STYLE_NONE) { ink = &ink_rect; logical = &logical_rect; @@ -622,7 +647,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, if (renderer->underline != PANGO_LINE_STYLE_NONE || renderer->priv->overline != PANGO_OVERLINE_NONE || - renderer->strikethrough) + renderer->strikethrough != PANGO_LINE_STYLE_NONE) { metrics = pango_font_get_metrics (run->item->analysis.font, run->item->analysis.language); @@ -637,7 +662,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, x + x_off, y - y_off, ink, logical); - if (renderer->strikethrough) + if (renderer->strikethrough != PANGO_LINE_STYLE_NONE) add_strikethrough (renderer, &state, metrics, x + x_off, y - y_off, ink, logical, run->glyphs->num_glyphs); @@ -653,7 +678,8 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer, state.overline != PANGO_OVERLINE_NONE) draw_overline (renderer, &state); - if (!renderer->strikethrough && state.strikethrough) + if (renderer->strikethrough == PANGO_LINE_STYLE_NONE && + state.strikethrough != PANGO_LINE_STYLE_NONE) draw_strikethrough (renderer, &state); x_off += glyph_string_width; @@ -1406,7 +1432,7 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer, renderer->underline = PANGO_LINE_STYLE_NONE; renderer->underline_position = PANGO_UNDERLINE_POSITION_NORMAL; renderer->priv->overline = PANGO_OVERLINE_NONE; - renderer->strikethrough = FALSE; + renderer->strikethrough = PANGO_LINE_STYLE_NONE; for (l = run->item->analysis.extra_attrs; l; l = l->next) { diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h index 6be251cd..6848f749 100644 --- a/pango/pango-renderer.h +++ b/pango/pango-renderer.h @@ -81,7 +81,7 @@ struct _PangoRenderer PangoLineStyle underline; PangoUnderlinePosition underline_position; - gboolean strikethrough; + PangoLineStyle strikethrough; int active_count; /*< public >*/ diff --git a/pango/serializer.c b/pango/serializer.c index 6ff7a3a4..61650b22 100644 --- a/pango/serializer.c +++ b/pango/serializer.c @@ -324,6 +324,7 @@ add_attribute (GtkJsonPrinter *printer, break; case PANGO_ATTR_UNDERLINE: + case PANGO_ATTR_STRIKETHROUGH: gtk_json_printer_add_string (printer, "value", line_style_names[attr->int_value]); break; @@ -1020,7 +1021,7 @@ attr_for_type (GtkJsonParser *parser, break; case PANGO_ATTR_STRIKETHROUGH: - attr = pango_attr_strikethrough_new (gtk_json_parser_get_boolean (parser)); + attr = pango_attr_strikethrough_new ((PangoLineStyle) parser_select_string (parser, line_style_names)); break; case PANGO_ATTR_RISE: -- cgit v1.2.1