summaryrefslogtreecommitdiff
path: root/pango/pango-renderer.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2019-08-22 11:46:07 +0200
committerMatthias Clasen <mclasen@redhat.com>2019-10-31 21:23:59 -0400
commitde0ab09cdbf5bdfa0caa365a22ac864e41838e48 (patch)
tree1651a116a7edd93defb2a608674d250d2505aedc /pango/pango-renderer.c
parent580bb08df7d7d8ac42558cee5bf4d2fc7986327b (diff)
downloadpango-de0ab09cdbf5bdfa0caa365a22ac864e41838e48.tar.gz
renderer: Implement overlines
Implement overlines in PangoRenderer. This adds a new render part, and mirrors the machinery we have for underlines and strikethrough.
Diffstat (limited to 'pango/pango-renderer.c')
-rw-r--r--pango/pango-renderer.c121
1 files changed, 120 insertions, 1 deletions
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 51403785..8180fbf3 100644
--- a/pango/pango-renderer.c
+++ b/pango/pango-renderer.c
@@ -26,7 +26,7 @@
#include "pango-impl-utils.h"
#include "pango-layout-private.h"
-#define N_RENDER_PARTS 4
+#define N_RENDER_PARTS 5
#define PANGO_IS_RENDERER_FAST(renderer) (renderer != NULL)
#define IS_VALID_PART(part) ((guint)part < N_RENDER_PARTS)
@@ -48,6 +48,9 @@ struct _LineState
PangoRectangle strikethrough_rect;
int strikethrough_glyphs;
+ PangoOverline overline;
+ PangoRectangle overline_rect;
+
int logical_rect_end;
};
@@ -247,6 +250,30 @@ draw_underline (PangoRenderer *renderer,
}
static void
+draw_overline (PangoRenderer *renderer,
+ LineState *state)
+{
+ PangoRectangle *rect = &state->overline_rect;
+ PangoOverline overline = state->overline;
+
+ state->overline = PANGO_OVERLINE_NONE;
+
+ switch (overline)
+ {
+ case PANGO_OVERLINE_NONE:
+ break;
+ case PANGO_OVERLINE_SINGLE:
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_OVERLINE,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+ break;
+ }
+}
+
+static void
draw_strikethrough (PangoRenderer *renderer,
LineState *state)
{
@@ -285,6 +312,18 @@ handle_line_state_change (PangoRenderer *renderer,
rect->width = 0;
}
+ if (part == PANGO_RENDER_PART_OVERLINE &&
+ state->overline != PANGO_OVERLINE_NONE)
+ {
+ PangoRectangle *rect = &state->overline_rect;
+
+ rect->width = state->logical_rect_end - rect->x;
+ draw_overline (renderer, state);
+ state->overline = renderer->overline;
+ rect->x = state->logical_rect_end;
+ rect->width = 0;
+ }
+
if (part == PANGO_RENDER_PART_STRIKETHROUGH &&
state->strikethrough)
{
@@ -361,6 +400,58 @@ add_underline (PangoRenderer *renderer,
}
static void
+add_overline (PangoRenderer *renderer,
+ LineState *state,
+ PangoFontMetrics *metrics,
+ int base_x,
+ int base_y,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoRectangle *current_rect = &state->overline_rect;
+ PangoRectangle new_rect;
+ int underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
+ int underline_position = pango_font_metrics_get_underline_position (metrics);
+ int ascent = pango_font_metrics_get_ascent (metrics);
+
+ new_rect.x = base_x + logical_rect->x;
+ new_rect.width = logical_rect->width;
+ new_rect.height = underline_thickness;
+ new_rect.y = base_y;
+
+ switch (renderer->overline)
+ {
+ case PANGO_OVERLINE_NONE:
+ g_assert_not_reached ();
+ break;
+ case PANGO_OVERLINE_SINGLE:
+ new_rect.y -= ascent + underline_position;
+ if (state->overline == renderer->overline)
+ {
+ new_rect.y = MIN (current_rect->y, new_rect.y);
+ new_rect.height = MAX (current_rect->height, new_rect.height);
+ current_rect->y = new_rect.y;
+ current_rect->height = new_rect.height;
+ }
+ break;
+ }
+
+ if (renderer->overline == state->overline &&
+ new_rect.y == current_rect->y &&
+ new_rect.height == current_rect->height)
+ {
+ current_rect->width = new_rect.x + new_rect.width - current_rect->x;
+ }
+ else
+ {
+ draw_overline (renderer, state);
+
+ *current_rect = new_rect;
+ state->overline = renderer->overline;
+ }
+}
+
+static void
add_strikethrough (PangoRenderer *renderer,
LineState *state,
PangoFontMetrics *metrics,
@@ -501,6 +592,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
renderer->priv->line_state = &state;
state.underline = PANGO_UNDERLINE_NONE;
+ state.overline = PANGO_OVERLINE_NONE;
state.strikethrough = FALSE;
text = G_LIKELY (line->layout) ? pango_layout_get_text (line->layout) : NULL;
@@ -535,6 +627,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
else
{
if (renderer->underline != PANGO_UNDERLINE_NONE ||
+ renderer->overline != PANGO_OVERLINE_NONE ||
renderer->strikethrough)
{
ink = &ink_rect;
@@ -592,6 +685,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
}
if (renderer->underline != PANGO_UNDERLINE_NONE ||
+ renderer->overline != PANGO_OVERLINE_NONE ||
renderer->strikethrough)
{
metrics = pango_font_get_metrics (run->item->analysis.font,
@@ -602,6 +696,11 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
x + x_off, y - rise,
ink, logical);
+ if (renderer->overline != PANGO_OVERLINE_NONE)
+ add_overline (renderer, &state,metrics,
+ x + x_off, y - rise,
+ ink, logical);
+
if (renderer->strikethrough)
add_strikethrough (renderer, &state, metrics,
x + x_off, y - rise,
@@ -614,6 +713,10 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
state.underline != PANGO_UNDERLINE_NONE)
draw_underline (renderer, &state);
+ if (renderer->overline == PANGO_OVERLINE_NONE &&
+ state.overline != PANGO_OVERLINE_NONE)
+ draw_overline (renderer, &state);
+
if (!renderer->strikethrough && state.strikethrough)
draw_strikethrough (renderer, &state);
@@ -623,6 +726,7 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
/* Finish off any remaining underlines
*/
draw_underline (renderer, &state);
+ draw_overline (renderer, &state);
draw_strikethrough (renderer, &state);
renderer->priv->line_state = NULL;
@@ -1332,12 +1436,14 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer,
PangoColor *fg_color = NULL;
PangoColor *bg_color = NULL;
PangoColor *underline_color = NULL;
+ PangoColor *overline_color = NULL;
PangoColor *strikethrough_color = NULL;
guint16 fg_alpha = 0;
guint16 bg_alpha = 0;
GSList *l;
renderer->underline = PANGO_UNDERLINE_NONE;
+ renderer->overline = PANGO_OVERLINE_NONE;
renderer->strikethrough = FALSE;
for (l = run->item->analysis.extra_attrs; l; l = l->next)
@@ -1350,6 +1456,10 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer,
renderer->underline = ((PangoAttrInt *)attr)->value;
break;
+ case PANGO_ATTR_OVERLINE:
+ renderer->overline = ((PangoAttrInt *)attr)->value;
+ break;
+
case PANGO_ATTR_STRIKETHROUGH:
renderer->strikethrough = ((PangoAttrInt *)attr)->value;
break;
@@ -1366,6 +1476,10 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer,
underline_color = &((PangoAttrColor *)attr)->color;
break;
+ case PANGO_ATTR_OVERLINE_COLOR:
+ overline_color = &((PangoAttrColor *)attr)->color;
+ break;
+
case PANGO_ATTR_STRIKETHROUGH_COLOR:
strikethrough_color = &((PangoAttrColor *)attr)->color;
break;
@@ -1386,6 +1500,9 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer,
if (!underline_color)
underline_color = fg_color;
+ if (!overline_color)
+ overline_color = fg_color;
+
if (!strikethrough_color)
strikethrough_color = fg_color;
@@ -1393,11 +1510,13 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer,
pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, bg_color);
pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, underline_color);
pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, strikethrough_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_OVERLINE, overline_color);
pango_renderer_set_alpha (renderer, PANGO_RENDER_PART_FOREGROUND, fg_alpha);
pango_renderer_set_alpha (renderer, PANGO_RENDER_PART_BACKGROUND, bg_alpha);
pango_renderer_set_alpha (renderer, PANGO_RENDER_PART_UNDERLINE, fg_alpha);
pango_renderer_set_alpha (renderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_alpha);
+ pango_renderer_set_alpha (renderer, PANGO_RENDER_PART_OVERLINE, fg_alpha);
}
/**