[pango] Add pango_shape_full()
- From: Behdad Esfahbod <behdad src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango] Add pango_shape_full()
- Date: Wed, 26 Sep 2012 19:44:15 +0000 (UTC)
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]