[pango] Add pango_shape_full()



commit bbec7e8697907a922f80c00b94f54b9b8634d264
Author: Behdad Esfahbod <behdad behdad org>
Date:   Wed Sep 26 15:37:20 2012 -0400

    Add pango_shape_full()
    
    Variant of pango_shape() that takes the full paragraph text as input.
    This is then passed in entirety to HarfBuzz, which would allow certain
    cross-run interactions (in Arabic for example).
    
    When combined with upcoming HarfBuzz 0.9.5+, this fixes:
    
    Red Hat Bug 858736 - [Spanish] Stray dotted circle rendered
    https://bugzilla.redhat.com/show_bug.cgi?id=858736
    
    and partially:
    
    Bug 313181 - color changes break arabic shaping
    https://bugzilla.gnome.org/show_bug.cgi?id=313181

 docs/pango-sections.txt      |    1 +
 modules/basic/basic-fc.c     |   16 +++++-----
 pango/pango-context.c        |   11 +++++--
 pango/pango-engine-private.h |   14 +++++----
 pango/pango-engine.c         |   19 ++++++++----
 pango/pango-engine.h         |   12 ++++---
 pango/pango-glyph.h          |    7 ++++
 pango/pango-impl-utils.h     |    2 +-
 pango/pango-layout.c         |    4 ++-
 pango/pango-utils.c          |    2 +-
 pango/pango.def              |    1 +
 pango/shape.c                |   63 ++++++++++++++++++++++++++++++++++++++---
 12 files changed, 115 insertions(+), 37 deletions(-)
---
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 93f256c..5f6ba73 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -53,6 +53,7 @@ pango_default_break
 PangoLogAttr
 <SUBSECTION>
 pango_shape
+pango_shape_full
 
 <SUBSECTION Private>
 pango_context_get_type
diff --git a/modules/basic/basic-fc.c b/modules/basic/basic-fc.c
index 1def055..ef0277e 100644
--- a/modules/basic/basic-fc.c
+++ b/modules/basic/basic-fc.c
@@ -295,12 +295,14 @@ pango_fc_get_hb_font_funcs (void)
 
 
 static void
-basic_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
-		    PangoFont        *font,
-		    const char       *text,
-		    gint              length,
+basic_engine_shape (PangoEngineShape    *engine G_GNUC_UNUSED,
+		    PangoFont           *font,
+		    const char          *item_text,
+		    unsigned int         item_length,
 		    const PangoAnalysis *analysis,
-		    PangoGlyphString *glyphs)
+		    PangoGlyphString    *glyphs,
+		    const char          *paragraph_text,
+		    unsigned int         paragraph_length)
 {
   PangoFcHbContext context;
   PangoFcFont *fc_font;
@@ -317,8 +319,6 @@ basic_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
   guint i, num_glyphs;
 
   g_return_if_fail (font != NULL);
-  g_return_if_fail (text != NULL);
-  g_return_if_fail (length >= 0);
   g_return_if_fail (analysis != NULL);
 
   fc_font = PANGO_FC_FONT (font);
@@ -362,7 +362,7 @@ basic_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
   hb_buffer_set_script (hb_buffer, hb_glib_script_to_script (analysis->script));
   hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis->language), -1));
 
-  hb_buffer_add_utf8 (hb_buffer, text, length, 0, length);
+  hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_text - paragraph_text, item_length);
   hb_shape (hb_font, hb_buffer, NULL, 0);
 
   if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 2a1e44f..341f92a 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -1646,6 +1646,7 @@ static void
 update_metrics_from_items (PangoFontMetrics *metrics,
 			   PangoLanguage    *language,
 			   const char       *text,
+			   unsigned int      text_len,
 			   GList            *items)
 
 {
@@ -1671,7 +1672,9 @@ update_metrics_from_items (PangoFontMetrics *metrics,
 	  pango_font_metrics_unref (raw_metrics);
 	}
 
-      pango_shape (text + item->offset, item->length, &item->analysis, glyphs);
+      pango_shape_full (text + item->offset, item->length,
+			text, text_len,
+			&item->analysis, glyphs);
       metrics->approximate_char_width += pango_glyph_string_get_width (glyphs);
     }
 
@@ -1716,6 +1719,7 @@ pango_context_get_metrics (PangoContext                 *context,
   PangoFontset *current_fonts = NULL;
   PangoFontMetrics *metrics;
   const char *sample_str;
+  unsigned int text_len;
   GList *items;
 
   g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
@@ -1730,9 +1734,10 @@ pango_context_get_metrics (PangoContext                 *context,
   metrics = get_base_metrics (current_fonts);
 
   sample_str = pango_language_get_sample_string (language);
-  items = itemize_with_font (context, sample_str, 0, strlen (sample_str), desc);
+  text_len = strlen (sample_str);
+  items = itemize_with_font (context, sample_str, 0, text_len, desc);
 
-  update_metrics_from_items (metrics, language, sample_str, items);
+  update_metrics_from_items (metrics, language, sample_str, text_len, items);
 
   g_list_foreach (items, (GFunc)pango_item_free, NULL);
   g_list_free (items);
diff --git a/pango/pango-engine-private.h b/pango/pango-engine-private.h
index 7d74302..760144e 100644
--- a/pango/pango-engine-private.h
+++ b/pango/pango-engine-private.h
@@ -27,12 +27,14 @@
 
 G_BEGIN_DECLS
 
-void               _pango_engine_shape_shape  (PangoEngineShape *engine,
-					       PangoFont        *font,
-					       const char       *text,
-					       int               length,
-					       const PangoAnalysis *analysis,
-					       PangoGlyphString *glyphs);
+void               _pango_engine_shape_shape (PangoEngineShape    *engine,
+					      PangoFont           *font,
+					      const char          *item_text,
+					      unsigned int         item_length,
+					      const char          *paragraph_text,
+					      unsigned int         paragraph_len,
+					      const PangoAnalysis *analysis,
+					      PangoGlyphString    *glyphs);
 PangoCoverageLevel _pango_engine_shape_covers (PangoEngineShape *engine,
 					       PangoFont        *font,
 					       PangoLanguage    *language,
diff --git a/pango/pango-engine.c b/pango/pango-engine.c
index 7b2c2fd..8a3369f 100644
--- a/pango/pango-engine.c
+++ b/pango/pango-engine.c
@@ -82,20 +82,25 @@ pango_engine_shape_class_init (PangoEngineShapeClass *class)
 }
 
 void
-_pango_engine_shape_shape (PangoEngineShape *engine,
-			   PangoFont        *font,
-			   const char       *text,
-			   int               length,
+_pango_engine_shape_shape (PangoEngineShape    *engine,
+			   PangoFont           *font,
+			   const char          *item_text,
+			   unsigned int         item_length,
+			   const char          *paragraph_text,
+			   unsigned int         paragraph_len,
 			   const PangoAnalysis *analysis,
-			   PangoGlyphString *glyphs)
+			   PangoGlyphString    *glyphs)
 {
   glyphs->num_glyphs = 0;
 
   PANGO_ENGINE_SHAPE_GET_CLASS (engine)->script_shape (engine,
 						       font,
-						       text, length,
+						       item_text,
+						       item_length,
 						       analysis,
-						       glyphs);
+						       glyphs,
+						       paragraph_text,
+						       paragraph_len);
 }
 
 PangoCoverageLevel
diff --git a/pango/pango-engine.h b/pango/pango-engine.h
index d14a982..51ac8c2 100644
--- a/pango/pango-engine.h
+++ b/pango/pango-engine.h
@@ -186,12 +186,14 @@ struct _PangoEngineShapeClass
   PangoEngineClass parent_class;
 
   /*< public >*/
-  void (*script_shape) (PangoEngineShape *engine,
-			PangoFont        *font,
-			const char       *text,
-			int               length,
+  void (*script_shape) (PangoEngineShape    *engine,
+			PangoFont           *font,
+			const char          *item_text,
+			unsigned int         item_length,
 			const PangoAnalysis *analysis,
-			PangoGlyphString *glyphs);
+			PangoGlyphString    *glyphs,
+			const char          *paragraph_text,
+			unsigned int         paragraph_length);
   PangoCoverageLevel (*covers)   (PangoEngineShape *engine,
 				  PangoFont        *font,
 				  PangoLanguage    *language,
diff --git a/pango/pango-glyph.h b/pango/pango-glyph.h
index 4af63e7..91bae32 100644
--- a/pango/pango-glyph.h
+++ b/pango/pango-glyph.h
@@ -128,6 +128,13 @@ void pango_shape (const gchar      *text,
 		  const PangoAnalysis *analysis,
 		  PangoGlyphString *glyphs);
 
+void pango_shape_full (const gchar      *item_text,
+		       gint              item_length,
+		       const gchar      *paragraph_text,
+		       gint              paragraph_length,
+		       const PangoAnalysis *analysis,
+		       PangoGlyphString *glyphs);
+
 GList *pango_reorder_items (GList *logical_items);
 
 G_END_DECLS
diff --git a/pango/pango-impl-utils.h b/pango/pango-impl-utils.h
index da3ef1c..9570da8 100644
--- a/pango/pango-impl-utils.h
+++ b/pango/pango-impl-utils.h
@@ -36,7 +36,7 @@ G_BEGIN_DECLS
 
 /* Some functions for handling PANGO_ATTR_SHAPE */
 void _pango_shape_shape (const char       *text,
-			 gint              n_chars,
+			 unsigned int      n_chars,
 			 PangoRectangle   *shape_ink,
 			 PangoRectangle   *shape_logical,
 			 PangoGlyphString *glyphs);
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 1cd9c39..48168d8 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -3181,7 +3181,9 @@ shape_run (PangoLayoutLine *line,
 			    state->properties.shape_ink_rect, state->properties.shape_logical_rect,
 			    glyphs);
       else
-	pango_shape (layout->text + item->offset, item->length, &item->analysis, glyphs);
+	pango_shape_full (layout->text + item->offset, item->length,
+			  layout->text, layout->length,
+			  &item->analysis, glyphs);
 
       if (state->properties.letter_spacing)
 	{
diff --git a/pango/pango-utils.c b/pango/pango-utils.c
index 112bc38..18ffa26 100644
--- a/pango/pango-utils.c
+++ b/pango/pango-utils.c
@@ -1131,7 +1131,7 @@ pango_extents_to_pixels (PangoRectangle *inclusive,
 
 void
 _pango_shape_shape (const char       *text,
-		    gint              n_chars,
+		    unsigned int      n_chars,
 		    PangoRectangle   *shape_ink G_GNUC_UNUSED,
 		    PangoRectangle   *shape_logical,
 		    PangoGlyphString *glyphs)
diff --git a/pango/pango.def b/pango/pango.def
index e573e3d..ba1289c 100644
--- a/pango/pango.def
+++ b/pango/pango.def
@@ -369,6 +369,7 @@ EXPORTS
 	pango_script_iter_new
 	pango_script_iter_next
 	pango_shape
+	pango_shape_full
 	pango_skip_space
 	pango_split_file_list
 	pango_stretch_get_type
diff --git a/pango/shape.c b/pango/shape.c
index 0fe3c95..63c36ab 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -38,6 +38,10 @@
  * #PangoAnalysis structure returned from pango_itemize(),
  * convert the characters into glyphs. You may also pass
  * in only a substring of the item from pango_itemize().
+ *
+ * It is recommended that you use pango_shape_full() instead, since
+ * that API allows for shaping interaction happening across text item
+ * boundaries.
  */
 void
 pango_shape (const gchar      *text,
@@ -45,15 +49,64 @@ pango_shape (const gchar      *text,
 	     const PangoAnalysis *analysis,
 	     PangoGlyphString *glyphs)
 {
+  pango_shape_full (text, length, text, length, analysis, glyphs);
+}
+
+/**
+ * pango_shape_full:
+ * @item_text:        valid UTF-8 text to shape.
+ * @item_length:      the length (in bytes) of @item_text. -1 means nul-terminated text.
+ * @paragraph_text: (allow-none)  text of the paragraph (see details).  May be %NULL.
+ * @paragraph_length: the length (in bytes) of @paragraph_text. -1 means nul-terminated text.
+ * @analysis:  #PangoAnalysis structure from pango_itemize().
+ * @glyphs:    glyph string in which to store results.
+ *
+ * Given a segment of text and the corresponding
+ * #PangoAnalysis structure returned from pango_itemize(),
+ * convert the characters into glyphs. You may also pass
+ * in only a substring of the item from pango_itemize().
+ *
+ * This is similar to pango_shape(), except it also can optionally take
+ * the full paragraph text as input, which will then be used to perform
+ * certain cross-item shaping interactions.  If you have access to the broader
+ * text of which @item_text is part of, provide the broader text as
+ * @paragraph_text.  If @paragraph_text is %NULL, item text is used instead.
+ *
+ * Since: 1.32
+ */
+void
+pango_shape_full (const gchar      *item_text,
+		  gint              item_length,
+		  const gchar      *paragraph_text,
+		  gint              paragraph_length,
+		  const PangoAnalysis *analysis,
+		  PangoGlyphString *glyphs)
+{
   int i;
   int last_cluster;
 
   glyphs->num_glyphs = 0;
 
+  if (item_length == -1)
+    item_length = strlen (item_text);
+
+  if (!paragraph_text)
+    {
+      paragraph_text = item_text;
+      paragraph_length = item_length;
+    }
+  if (paragraph_length == -1)
+    paragraph_length = strlen (paragraph_text);
+
+  g_return_if_fail (paragraph_text <= item_text);
+  g_return_if_fail (paragraph_text + paragraph_length >= item_text + item_length);
+
   if (G_LIKELY (analysis->shape_engine && analysis->font))
     {
       _pango_engine_shape_shape (analysis->shape_engine, analysis->font,
-				 text, length, analysis, glyphs);
+				 item_text, item_length,
+				 paragraph_text, paragraph_length,
+				 analysis, glyphs);
 
       if (G_UNLIKELY (glyphs->num_glyphs == 0))
 	{
@@ -90,9 +143,7 @@ pango_shape (const gchar      *text,
 		    engine_name = "(unknown)";
 
 		  g_warning ("shaping failure, expect ugly output. shape-engine='%s', font='%s', text='%.*s'",
-			     engine_name,
-			     font_name,
-			     length == -1 ? (gint) strlen (text) : length, text);
+			     engine_name, font_name, item_length, item_text);
 
 		  g_object_set_data_full (G_OBJECT (analysis->shape_engine), font_name,
 					  GINT_TO_POINTER (1), NULL);
@@ -113,7 +164,9 @@ pango_shape (const gchar      *text,
       PangoEngineShape *fallback_engine = _pango_get_fallback_shaper ();
 
       _pango_engine_shape_shape (fallback_engine, analysis->font,
-				 text, length, analysis, glyphs);
+				 item_text, item_length,
+				 paragraph_text, paragraph_length,
+				 analysis, glyphs);
       if (G_UNLIKELY (!glyphs->num_glyphs))
         return;
     }



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