[pango/space-itemization] itemize: Improve handling of spaces




commit ef9d296e6f293d415624e72125dc60d863547404
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jul 9 19:26:19 2021 -0400

    itemize: Improve handling of spaces
    
    Put spaces into the previous or the next item, depending
    on which one has the 'better' font.
    
    See: #249

 pango/pango-context.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 4 deletions(-)
---
diff --git a/pango/pango-context.c b/pango/pango-context.c
index ba77e1d3..1c7aaa32 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -779,6 +779,8 @@ struct _ItemizeState
   FontCache *cache;
   PangoFont *base_font;
   gboolean enable_fallback;
+
+  const char *first_space;
 };
 
 static void
@@ -1089,7 +1091,7 @@ itemize_state_init (ItemizeState               *state,
   state->current_fonts = NULL;
   state->cache = NULL;
   state->base_font = NULL;
-
+  state->first_space = NULL;
 }
 
 static gboolean
@@ -1171,10 +1173,24 @@ static void
 itemize_state_add_character (ItemizeState *state,
                              PangoFont    *font,
                              gboolean      force_break,
-                             const char   *pos)
+                             const char   *pos,
+                             gboolean      is_space)
 {
+  const char *first_space = state->first_space;
+  int n_spaces = 0;
+
+  if (is_space)
+    {
+      if (state->first_space == NULL)
+        state->first_space = pos;
+    }
+  else
+    state->first_space = NULL;
+
   if (state->item)
     {
+      int font_pos, new_pos;
+
       if (!state->item->analysis.font && font)
         {
           itemize_state_fill_font (state, font);
@@ -1191,13 +1207,26 @@ itemize_state_add_character (ItemizeState *state,
           return;
         }
 
+      if (state->item->analysis.font && font && state->text + state->item->offset < first_space)
+        {
+          font_pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (state->item->analysis.font), 
"pango_font_position"));
+          new_pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (font), "pango_font_position"));
+          if (new_pos < font_pos)
+            {
+              /* new font is "better", claw back spaces from the current item */
+              n_spaces = g_utf8_strlen (first_space, pos - first_space);
+              state->item->num_chars -= n_spaces;
+              pos = first_space;
+            }
+        }
+
       state->item->length = (pos - state->text) - state->item->offset;
     }
 
   state->item = pango_item_new ();
   state->item->offset = pos - state->text;
   state->item->length = 0;
-  state->item->num_chars = 1;
+  state->item->num_chars = n_spaces + 1;
 
   if (font)
     g_object_ref (font);
@@ -1259,6 +1288,7 @@ typedef struct {
   PangoLanguage *lang;
   gunichar wc;
   PangoFont *font;
+  int position;
 } GetFontInfo;
 
 static gboolean
@@ -1283,6 +1313,8 @@ get_font_foreach (PangoFontset *fontset,
       return TRUE;
     }
 
+  info->position++;
+
   return FALSE;
 }
 
@@ -1311,6 +1343,7 @@ get_font (ItemizeState  *state,
   info.lang = state->derived_lang;
   info.wc = wc;
   info.font = NULL;
+  info.position = 0;
 
   if (state->enable_fallback)
     pango_fontset_foreach (state->current_fonts, get_font_foreach, &info);
@@ -1318,6 +1351,8 @@ get_font (ItemizeState  *state,
     get_font_foreach (NULL, get_base_font (state), &info);
 
   *font = info.font;
+  if (*font)
+    g_object_set_data (G_OBJECT (*font), "pango_font_position", GINT_TO_POINTER (info.position));
 
   /* skip caching if fallback disabled (see above) */
   if (state->enable_fallback)
@@ -1436,6 +1471,7 @@ itemize_state_process_run (ItemizeState *state)
 {
   const char *p;
   gboolean last_was_forced_break = FALSE;
+  gboolean is_space;
 
   /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 4.0;
    * update this if that changes. */
@@ -1478,15 +1514,18 @@ itemize_state_process_run (ItemizeState *state)
                       (wc >= 0xe0100u && wc <= 0xe01efu)))
         {
           font = NULL;
+          is_space = TRUE;
         }
       else
         {
           get_font (state, wc, &font);
+          is_space = FALSE;
         }
 
       itemize_state_add_character (state, font,
                                    is_forced_break || last_was_forced_break,
-                                   p);
+                                   p,
+                                   is_space);
 
       last_was_forced_break = is_forced_break;
     }


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