Blob Blame History Raw
From d9488d4dc49559c8adc4ab6b7156393782ee4ab9 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 11 Aug 2022 22:32:30 +0200
Subject: [PATCH 1/5] Fix text_layout::compute_line_width()

Before this refactoring when compute_line_width() hit this:

          result =
            candidate_length
            - m_font.get_metrics( m_text[ last ] ).get_advance().x;

path then last has been incremented 1 from the positon when the:
candidate_length += m_font.get_metrics( m_text[last] ).get_advance().x;
was executed, if the new position has a smaller width character,
say a '.' then candidate_length might still be too long after
the substraction, triggering the:

  CLAW_POSTCOND( result <= m_size.x );

assert, crashing the application.

To fix this move the candidate_length > m_size.x check to inside
the loop, before actually incrementing candidate_length and last.
This also allows dropping the line_full flag and generally
simplifies things a bit.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../core/src/visual/code/text_layout.cpp      | 54 +++++++++----------
 1 file changed, 26 insertions(+), 28 deletions(-)

diff --git a/bear-engine/core/src/visual/code/text_layout.cpp b/bear-engine/core/src/visual/code/text_layout.cpp
index 77820e6..33f3047 100644
--- a/bear-engine/core/src/visual/code/text_layout.cpp
+++ b/bear-engine/core/src/visual/code/text_layout.cpp
@@ -82,45 +82,43 @@ bear::visual::text_layout::compute_line_width( std::size_t first ) const
 
   size_type result(0);
   size_type candidate_length(0);
+  size_type width(0);
 
   // The line ends on the last space character such that the next word would not
   // fit on the line.
   std::string::size_type last_space_sequence( std::string::npos );
-  bool line_full(false);
 
-  while ( (last != text_length) && (m_text[last] != '\n') && !line_full )
-    if ( candidate_length > m_size.x )
-      line_full = true;
-    else
-      {
-        if ( m_text[last] == ' ' )
-          {
-            if ( last_space_sequence == std::string::npos )
-              {
-                last_space_sequence = last;
-                result = candidate_length;
-              }
-          }
-        else
-          last_space_sequence = std::string::npos;
-      
-        candidate_length += m_font.get_metrics( m_text[last] ).get_advance().x;
-        ++last;
-      }
+  while ( (last != text_length) && (m_text[last] != '\n') )
+    {
+      if ( m_text[last] == ' ' )
+        {
+          if ( last_space_sequence == std::string::npos )
+            {
+              last_space_sequence = last;
+              result = candidate_length;
+            }
+        }
+      else
+        last_space_sequence = std::string::npos;
+
+      width = m_font.get_metrics( m_text[last] ).get_advance().x;
+      if ( (candidate_length + width) > m_size.x )
+        break;
+
+      candidate_length += width;
+      ++last;
+    }
 
   // if we stopped in the middle of a word or at the end of the line, then we
   // must adjust the result from the candidate length.
   if ( last_space_sequence == std::string::npos )
     {
-      if ( (candidate_length <= m_size.x)
-           && ( (last == text_length) || !line_full ) )
+      // if we stopped at the end of line then the entire line fits
+      if ( (last == text_length) || (m_text[last] == '\n') )
+        result = candidate_length;
+      // else if we did not find a space to break at, use whatever fits
+      else if ( result == 0 )
         result = candidate_length;
-      else if ( (result == 0) && (candidate_length > 0) )
-        {
-          result =
-            candidate_length
-            - m_font.get_metrics( m_text[ last ] ).get_advance().x;
-        }
     }
 
   CLAW_POSTCOND( result >= 0 );
-- 
2.37.1