summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2012-09-26 15:37:20 -0400
committerBehdad Esfahbod <behdad@behdad.org>2012-09-26 15:37:20 -0400
commitbbec7e8697907a922f80c00b94f54b9b8634d264 (patch)
tree18c737c4c838199b9e6ca72383afdcd09e874af5
parent1c151fef87c61e2d329d84d3db59559bffa767fe (diff)
downloadpango-bbec7e8697907a922f80c00b94f54b9b8634d264.tar.gz
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
-rw-r--r--docs/pango-sections.txt1
-rw-r--r--modules/basic/basic-fc.c16
-rw-r--r--pango/pango-context.c11
-rw-r--r--pango/pango-engine-private.h14
-rw-r--r--pango/pango-engine.c19
-rw-r--r--pango/pango-engine.h12
-rw-r--r--pango/pango-glyph.h7
-rw-r--r--pango/pango-impl-utils.h2
-rw-r--r--pango/pango-layout.c4
-rw-r--r--pango/pango-utils.c2
-rw-r--r--pango/pango.def1
-rw-r--r--pango/shape.c63
12 files changed, 115 insertions, 37 deletions
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 93f256c5..5f6ba73c 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 1def0552..ef0277ea 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 2a1e44f3..341f92a6 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 7d743027..760144ec 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 7b2c2fd6..8a3369f3 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 d14a9827..51ac8c2e 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 4af63e78..91bae32a 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 da3ef1cb..9570da80 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 1cd9c39a..48168d82 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 112bc388..18ffa263 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 e573e3db..ba1289ce 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 0fe3c953..63c36ab7 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;
}