[pango/better-hyphens: 61/66] break: Implement allow-breaks



commit c7c8d8120925f83c638cc496b3f4de07aed442d0
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 20 10:36:48 2019 -0700

    break: Implement allow-breaks
    
    We implement this in pango_tailor_break(),
    after the script-specific breaking.
    
    When line breaks are forbidden in a range,
    we remove line and char break opportunities
    inside the range.

 pango/break.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 87 insertions(+), 9 deletions(-)
---
diff --git a/pango/break.c b/pango/break.c
index d25d2616..cde43fcb 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -1578,18 +1578,34 @@ break_script (const char          *item_text,
              int                  attrs_len);
 
 static gboolean
-tailor_break (const gchar   *text,
-            gint           length,
-            PangoAnalysis *analysis,
-            PangoLogAttr  *attrs,
-            int            attrs_len)
+break_attrs (const char   *text,
+            int           length,
+             GSList       *attributes,
+             int           item_offset,
+             PangoLogAttr *attrs,
+             int           attrs_len);
+
+static gboolean
+tailor_break (const char    *text,
+             int            length,
+             PangoAnalysis *analysis,
+              int            item_offset,
+             PangoLogAttr  *attrs,
+             int            attrs_len)
 {
+  gboolean res;
+
   if (length < 0)
     length = strlen (text);
   else if (text == NULL)
     text = "";
 
-  return break_script (text, length, analysis, attrs, attrs_len);
+  res = break_script (text, length, analysis, attrs, attrs_len);
+
+  if (item_offset >= 0)
+    res |= break_attrs (text, length, analysis->extra_attrs, item_offset, attrs, attrs_len);
+
+  return res;
 }
 
 /**
@@ -1618,7 +1634,7 @@ pango_break (const gchar   *text,
   g_return_if_fail (attrs != NULL);
 
   pango_default_break (text, length, analysis, attrs, attrs_len);
-  tailor_break        (text, length, analysis, attrs, attrs_len);
+  tailor_break        (text, length, analysis, -1, attrs, attrs_len);
 }
 
 /**
@@ -1726,7 +1742,8 @@ pango_find_paragraph_boundary (const gchar *text,
  * @text: text to process. Must be valid UTF-8
  * @length: length in bytes of @text
  * @analysis:  #PangoAnalysis structure from pango_itemize() for @text
- * @offset: byte offset of @text in paragraph, or -1
+ * @offset: Byte offset of @text from the beginning of the
+ *     paragraph, or -1 to ignore attributes from @analysis
  * @log_attrs: (array length=attrs_len): array with one #PangoLogAttr
  *   per character in @text, plus one extra, to be filled in
  * @attrs_len: length of @log_attrs array
@@ -1734,6 +1751,9 @@ pango_find_paragraph_boundary (const gchar *text,
  * Apply language-specific tailoring to the breaks in
  * @log_attrs, which are assumed to have been produced
  * by pango_default_break().
+ *
+ * If @offset is not -1, it is used to apply attributes
+ * from @analysis that are relevant to line breaking.
  */
 void
 pango_tailor_break (const char    *text,
@@ -1746,7 +1766,7 @@ pango_tailor_break (const char    *text,
   PangoLogAttr *start = log_attrs;
   PangoLogAttr attr_before = *start;
 
-  if (tailor_break (text, length, analysis, log_attrs, log_attrs_len))
+  if (tailor_break (text, length, analysis, offset, log_attrs, log_attrs_len))
     {
       /* if tailored, we enforce some of the attrs from before
        * tailoring at the boundary
@@ -1775,6 +1795,7 @@ tailor_segment (const char      *range_start,
   pango_tailor_break (range_start,
                       range_end - range_start,
                       analysis,
+                      -1,
                       start,
                       chars_in_range + 1);
 
@@ -1879,3 +1900,60 @@ break_script (const char          *item_text,
 
   return TRUE;
 }
+
+static gboolean
+break_attrs (const char   *text,
+             int           length,
+             GSList       *attributes,
+             int           offset,
+             PangoLogAttr *log_attrs,
+             int           log_attrs_len)
+{
+  PangoAttrList *list;
+  PangoAttrIterator *iter;
+  GSList *l;
+
+  list = pango_attr_list_new ();
+  for (l = attributes; l; l = l->next)
+    {
+      PangoAttribute *attr = l->data;
+
+      if (attr->klass->type == PANGO_ATTR_ALLOW_BREAKS)
+        pango_attr_list_insert (list, (PangoAttribute*)l->data);
+    }
+
+  iter = pango_attr_list_get_iterator (list);
+  do {
+    PangoAttribute *attr;
+
+    attr = pango_attr_iterator_get (iter, PANGO_ATTR_ALLOW_BREAKS);
+    if (attr && ((PangoAttrInt*)attr)->value == 0)
+      {
+        int start, end;
+        int start_pos, end_pos;
+        int pos;
+
+        pango_attr_iterator_range (iter, &start, &end);
+        if (start < offset)
+          start_pos = 0;
+        else
+          start_pos = g_utf8_pointer_to_offset (text, text + start - offset);
+        if (end >= offset + length)
+          end_pos = log_attrs_len;
+        else
+          end_pos = g_utf8_pointer_to_offset (text, text + end - offset);
+
+        for (pos = start_pos + 1; pos < end_pos; pos++)
+          {
+            log_attrs[pos].is_mandatory_break = FALSE;
+            log_attrs[pos].is_line_break = FALSE;
+            log_attrs[pos].is_char_break = FALSE;
+          }
+      }
+  } while (pango_attr_iterator_next (iter));
+
+  pango_attr_iterator_destroy (iter);
+  pango_attr_list_unref (list);
+
+  return TRUE;
+}


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