[pango/line-underline: 16/18] renderer: Implement overlines



commit 20879199f5a3653c97738cb2ed6635ce92bd5e40
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Aug 22 11:46:07 2019 +0200

    renderer: Implement overlines
    
    Implement overlines in PangoRenderer.
    This adds a new render part, and mirrors
    the machinery we have for underlines and
    strikethrough.

 pango/pango-renderer.c    | 121 +++++++++++++++++++++++++++++++++++++++++++++-
 pango/pango-renderer.h    |   5 +-
 pango/pangocairo-render.c |   2 +
 3 files changed, 126 insertions(+), 2 deletions(-)
---
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 51403785..7f824f32 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;
 };
 
@@ -246,6 +249,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)
     {
@@ -360,6 +399,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);
+
+  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 += ink_rect->y - underline_thickness + 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,
@@ -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);
 }
 
 /**
diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h
index 8a70a88a..4dae6a92 100644
--- a/pango/pango-renderer.h
+++ b/pango/pango-renderer.h
@@ -42,6 +42,7 @@ typedef struct _PangoRendererPrivate PangoRendererPrivate;
  * @PANGO_RENDER_PART_BACKGROUND: the area behind the text
  * @PANGO_RENDER_PART_UNDERLINE: underlines
  * @PANGO_RENDER_PART_STRIKETHROUGH: strikethrough lines
+ * @PANGO_RENDER_PART_OVERLINE: overlines
  *
  * #PangoRenderPart defines different items to render for such
  * purposes as setting colors.
@@ -54,7 +55,8 @@ typedef enum
   PANGO_RENDER_PART_FOREGROUND,
   PANGO_RENDER_PART_BACKGROUND,
   PANGO_RENDER_PART_UNDERLINE,
-  PANGO_RENDER_PART_STRIKETHROUGH
+  PANGO_RENDER_PART_STRIKETHROUGH,
+  PANGO_RENDER_PART_OVERLINE
 } PangoRenderPart;
 
 /**
@@ -75,6 +77,7 @@ struct _PangoRenderer
   GObject parent_instance;
 
   PangoUnderline underline;
+  PangoOverline overline;
   gboolean strikethrough;
   int active_count;
 
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index f4c57a87..e268ebd5 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -1051,6 +1051,7 @@ _pango_cairo_do_glyph_string (cairo_t          *cr,
       pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, NULL);
       pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, NULL);
       pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, NULL);
+      pango_renderer_set_color (renderer, PANGO_RENDER_PART_OVERLINE, NULL);
     }
 
   pango_renderer_draw_glyphs (renderer, font, glyphs, 0, 0);
@@ -1090,6 +1091,7 @@ _pango_cairo_do_glyph_item (cairo_t          *cr,
       pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, NULL);
       pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, NULL);
       pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, NULL);
+      pango_renderer_set_color (renderer, PANGO_RENDER_PART_OVERLINE, NULL);
     }
 
   pango_renderer_draw_glyph_item (renderer, text, glyph_item, 0, 0);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]