Bug 347146 – underline/overstrike spaces
authorBehdad Esfahbod <behdad@gnome.org>
Mon, 11 Sep 2006 16:22:33 +0000 (16:22 +0000)
committerBehdad Esfahbod <behdad@src.gnome.org>
Mon, 11 Sep 2006 16:22:33 +0000 (16:22 +0000)
2006-09-11  Behdad Esfahbod  <behdad@gnome.org>

        Bug 347146 – underline/overstrike spaces

        * pango/pango-renderer.c (add_underline), (add_strikethrough),
        (pango_renderer_draw_layout_line): Use logical extents for
        x and width of underline/strikethrough, such that trailing spaces are
        correctly handled.

        * pango/pango-layout.c (pango_layout_run_get_extents): Use logical
        rect for underline/strikethrough, and reflect that in run ink extents.

        * pango/pango-layout.c (pango_layout_line_get_extents): Don't
        let runs with empty ink extents affect total ink extents.

ChangeLog
pango/pango-layout.c
pango/pango-renderer.c

index 03c13dc..c97f873 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-09-11  Behdad Esfahbod  <behdad@gnome.org>
+
+       Bug 347146 – underline/overstrike spaces
+
+       * pango/pango-renderer.c (add_underline), (add_strikethrough),
+       (pango_renderer_draw_layout_line): Use logical extents for
+       x and width of underline/strikethrough, such that trailing spaces are
+       correctly handled.
+
+       * pango/pango-layout.c (pango_layout_run_get_extents): Use logical
+       rect for underline/strikethrough, and reflect that in run ink extents.
+
+       * pango/pango-layout.c (pango_layout_line_get_extents): Don't
+       let runs with empty ink extents affect total ink extents.
+
 2006-09-10  Behdad Esfahbod  <behdad@gnome.org>
 
        Bug 352535 – Ink extents of empty glyph
index 456ca64..1389e00 100644 (file)
@@ -47,6 +47,7 @@ struct _Extents
 struct _ItemProperties
 {
   PangoUnderline  uline;
+  gboolean        strikethrough;
   gint            rise;
   gint            letter_spacing;
   gboolean        shape_set;
@@ -3960,6 +3961,9 @@ pango_layout_run_get_extents (PangoLayoutRun *run,
   if (!run_logical && run->item->analysis.centered_baseline)
     run_logical = &logical;
 
+  if (!run_logical && (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough))
+    run_logical = &logical;
+
   if (properties.shape_set)
     imposed_extents (run->item->num_chars,
                     properties.shape_ink_rect,
@@ -3969,33 +3973,55 @@ pango_layout_run_get_extents (PangoLayoutRun *run,
     pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
                                run_ink, run_logical);
 
-  if (properties.uline != PANGO_UNDERLINE_NONE)
+  if (run_ink && (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough))
     {
       PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font,
                                                          run->item->analysis.language); 
       int underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
       int underline_position = pango_font_metrics_get_underline_position (metrics);
+      int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
+      int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
+
+      int new_pos;
+
+      /* the underline/strikethrough takes x,width of logical_rect.  reflect
+       * that into ink_rect.
+       */
+      new_pos = MIN (run_ink->x, run_logical->x);
+      run_ink->width = MAX (run_ink->x + run_ink->width, run_logical->x + run_logical->width) - new_pos;
+      run_ink->x = new_pos;
+
+      /* We should better handle the case of height==0 in the following cases.
+       * If run_ink->height == 0, we should adjust run_ink->y appropriately.
+       */
+
+      if (properties.strikethrough)
+        {
+         if (run_ink->height == 0)
+           {
+             run_ink->height = strikethrough_thickness;
+             run_ink->y = -strikethrough_position;
+           }
+       }
 
       switch (properties.uline)
        {
        case PANGO_UNDERLINE_ERROR:
-         if (run_ink)
-           run_ink->height = MAX (run_ink->height,
-                                  3 * underline_thickness - underline_position - run_ink->y);
+         run_ink->height = MAX (run_ink->height,
+                                3 * underline_thickness - underline_position - run_ink->y);
          break;
        case PANGO_UNDERLINE_SINGLE:
-         if (run_ink)
-           run_ink->height = MAX (run_ink->height,
-                                  underline_thickness - underline_position - run_ink->y);
+         run_ink->height = MAX (run_ink->height,
+                                underline_thickness - underline_position - run_ink->y);
          break;
        case PANGO_UNDERLINE_DOUBLE:
-         if (run_ink)
-           run_ink->height = MAX (run_ink->height,
-                                  3 * underline_thickness - underline_position - run_ink->y);
+         run_ink->height = MAX (run_ink->height,
+                                3 * underline_thickness - underline_position - run_ink->y);
          break;
        case PANGO_UNDERLINE_LOW:
-         if (run_ink)
-           run_ink->height += 2 * underline_thickness;
+         run_ink->height += 2 * underline_thickness;
+         break;
+       case PANGO_UNDERLINE_NONE:
          break;
        default:
          g_critical ("unknown underline mode");
@@ -4073,11 +4099,12 @@ pango_layout_line_get_extents (PangoLayoutLine *line,
       
       if (ink_rect)
        {
-         if (tmp_list == line->runs)
+         if (ink_rect->width == 0 || ink_rect->height == 0)
            {
              *ink_rect = run_ink;
+             ink_rect->x += x_pos;
            }
-         else
+         else if (run_ink.width != 0 && run_ink.height != 0)
            {
              new_pos = MIN (ink_rect->x, x_pos + run_ink.x);
              ink_rect->width = MAX (ink_rect->x + ink_rect->width,
@@ -4390,6 +4417,7 @@ pango_layout_get_item_properties (PangoItem      *item,
   GSList *tmp_list = item->analysis.extra_attrs;
 
   properties->uline = PANGO_UNDERLINE_NONE;
+  properties->strikethrough = FALSE;
   properties->letter_spacing = 0;
   properties->rise = 0;
   properties->shape_set = FALSE;
@@ -4406,6 +4434,10 @@ pango_layout_get_item_properties (PangoItem      *item,
          properties->uline = ((PangoAttrInt *)attr)->value;
          break;
 
+       case PANGO_ATTR_STRIKETHROUGH:
+         properties->strikethrough = ((PangoAttrInt *)attr)->value;
+         break;
+         
         case PANGO_ATTR_RISE:
          properties->rise = ((PangoAttrInt *)attr)->value;
           break;
index f54e128..7d165f8 100644 (file)
@@ -289,7 +289,8 @@ add_underline (PangoRenderer    *renderer,
               PangoFontMetrics *metrics,
               int               base_x,
               int               base_y,
-              PangoRectangle   *ink_rect)
+              PangoRectangle   *ink_rect,
+              PangoRectangle   *logical_rect)
 {
   PangoRectangle *current_rect = &state->underline_rect;
   PangoRectangle new_rect;
@@ -297,8 +298,8 @@ add_underline (PangoRenderer    *renderer,
   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 + ink_rect->x;
-  new_rect.width = ink_rect->width;
+  new_rect.x = base_x + logical_rect->x;
+  new_rect.width = logical_rect->width;
   new_rect.height = underline_thickness;
   new_rect.y = base_y;
   
@@ -316,14 +317,13 @@ add_underline (PangoRenderer    *renderer,
       new_rect.y += ink_rect->y + ink_rect->height + underline_thickness;
       break;
     }
+      int new_pos;
   
   if (renderer->underline == state->underline &&
       new_rect.y == current_rect->y &&
       new_rect.height == current_rect->height)
     {
-      current_rect->y = new_rect.y;
       current_rect->width = new_rect.x + new_rect.width - current_rect->x;
-      current_rect->height = new_rect.height;
     }
   else
     {
@@ -340,7 +340,8 @@ add_strikethrough (PangoRenderer    *renderer,
                   PangoFontMetrics *metrics,
                   int               base_x,
                   int               base_y,
-                  PangoRectangle   *ink_rect)
+                  PangoRectangle   *ink_rect,
+                  PangoRectangle   *logical_rect)
 {
   PangoRectangle *current_rect = &state->strikethrough_rect;
   PangoRectangle new_rect;
@@ -348,8 +349,8 @@ add_strikethrough (PangoRenderer    *renderer,
   int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
   int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
   
-  new_rect.x = base_x + ink_rect->x;
-  new_rect.width = ink_rect->width;
+  new_rect.x = base_x + logical_rect->x;
+  new_rect.width = logical_rect->width;
   new_rect.y = base_y - strikethrough_position;
   new_rect.height = strikethrough_thickness;
   
@@ -357,9 +358,7 @@ add_strikethrough (PangoRenderer    *renderer,
       new_rect.y == current_rect->y &&
       new_rect.height == current_rect->height)
     {
-      current_rect->y = new_rect.y;
       current_rect->width = new_rect.x + new_rect.width - current_rect->x;
-      current_rect->height = new_rect.height;
     }
   else
     {
@@ -493,13 +492,18 @@ pango_renderer_draw_layout_line (PangoRenderer    *renderer,
        {
          ink_rect = shape_attr->ink_rect;
          logical_rect = shape_attr->logical_rect;
+         ink = &ink_rect;
+         logical = &logical_rect;
          glyph_string_width = shape_attr->logical_rect.width;
        }
       else
        {
          if (renderer->underline != PANGO_UNDERLINE_NONE ||
              renderer->strikethrough)
-           ink = &ink_rect;
+           {
+             ink = &ink_rect;
+             logical = &logical_rect;
+           }
          pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
                                      ink, logical);
          if (logical)
@@ -550,12 +554,12 @@ pango_renderer_draw_layout_line (PangoRenderer    *renderer,
          if (renderer->underline != PANGO_UNDERLINE_NONE)
            add_underline (renderer, &state,metrics,
                           x + x_off, y - rise,
-                          &ink_rect);
+                          ink, logical);
          
          if (renderer->strikethrough)
            add_strikethrough (renderer, &state, metrics,
                               x + x_off, y - rise,
-                              &ink_rect);
+                              ink, logical);
          
          pango_font_metrics_unref (metrics);
        }