summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2009-11-17 16:20:42 -0500
committerBehdad Esfahbod <behdad@behdad.org>2009-11-17 16:21:11 -0500
commit4ccabeffc20f899163bf610356871afb197e9bf8 (patch)
tree629478f89f68fc763f55cbc53bd8d1d25160c610
parent718c533d28cb760e45c7b874420b14003445a9c1 (diff)
downloadpango-4ccabeffc20f899163bf610356871afb197e9bf8.tar.gz
Bug 596614 - Pango application receives SIGSEGV on pasting text with U+202E
Fixed all modules to reverse glyphs if run is rtl. Except for Hangul module. Fixed pango_shape() to detect that, warn, and reverse.
-rw-r--r--modules/indic/indic-fc.c1
-rw-r--r--modules/khmer/khmer-fc.c1
-rw-r--r--modules/thai/thai-fc.c1
-rw-r--r--modules/tibetan/tibetan-fc.c1
-rw-r--r--pango/glyphstring.c2
-rw-r--r--pango/pango-engine.c3
-rw-r--r--pango/pango-impl-utils.h26
-rw-r--r--pango/pango-ot-buffer.c23
-rw-r--r--pango/shape.c34
9 files changed, 65 insertions, 27 deletions
diff --git a/modules/indic/indic-fc.c b/modules/indic/indic-fc.c
index 6ba90c1a..3a232be4 100644
--- a/modules/indic/indic-fc.c
+++ b/modules/indic/indic-fc.c
@@ -252,6 +252,7 @@ indic_engine_shape (PangoEngineShape *engine,
pango_glyph_string_set_size (glyphs, n_glyphs);
buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
set_glyphs(font, wc_out, tags, n_glyphs, buffer,
(indic_shape_engine->classTable->scriptFlags & SF_PROCESS_ZWJ) != 0);
diff --git a/modules/khmer/khmer-fc.c b/modules/khmer/khmer-fc.c
index 04c5c830..14357d78 100644
--- a/modules/khmer/khmer-fc.c
+++ b/modules/khmer/khmer-fc.c
@@ -481,6 +481,7 @@ khmer_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
return;
buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
diff --git a/modules/thai/thai-fc.c b/modules/thai/thai-fc.c
index 66dccbb4..837a0286 100644
--- a/modules/thai/thai-fc.c
+++ b/modules/thai/thai-fc.c
@@ -298,6 +298,7 @@ thai_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
thai_set_glyphs (font_info, text, length, analysis->script, glyphs);
buffer = pango_ot_buffer_new (PANGO_FC_FONT (font));
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
for (i = 0; i < glyphs->num_glyphs; i++)
pango_ot_buffer_add_glyph (buffer,
diff --git a/modules/tibetan/tibetan-fc.c b/modules/tibetan/tibetan-fc.c
index 51600fc8..4e894165 100644
--- a/modules/tibetan/tibetan-fc.c
+++ b/modules/tibetan/tibetan-fc.c
@@ -443,6 +443,7 @@ tibetan_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
return;
buffer = pango_ot_buffer_new (fc_font);
+ pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
diff --git a/pango/glyphstring.c b/pango/glyphstring.c
index 923a9360..0382eb6e 100644
--- a/pango/glyphstring.c
+++ b/pango/glyphstring.c
@@ -659,5 +659,3 @@ pango_glyph_string_x_to_index (PangoGlyphString *glyphs,
}
}
}
-
-
diff --git a/pango/pango-engine.c b/pango/pango-engine.c
index 974e2d5a..50ba7f40 100644
--- a/pango/pango-engine.c
+++ b/pango/pango-engine.c
@@ -140,6 +140,9 @@ fallback_engine_shape (PangoEngineShape *engine G_GNUC_UNUSED,
p = g_utf8_next_char (p);
}
+
+ if (analysis->level & 1)
+ pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
}
static PangoCoverageLevel
diff --git a/pango/pango-impl-utils.h b/pango/pango-impl-utils.h
index 3ef3a0c4..6d6c8ff2 100644
--- a/pango/pango-impl-utils.h
+++ b/pango/pango-impl-utils.h
@@ -150,7 +150,31 @@ pango_utf8_strlen (const gchar *p, gssize max)
return len;
}
+
+/* To be made public at some point */
+
+static G_GNUC_UNUSED void
+pango_glyph_string_reverse_range (PangoGlyphString *glyphs,
+ int start, int end)
+{
+ int i, j;
+
+ for (i = start, j = end - 1; i < j; i++, j--)
+ {
+ PangoGlyphInfo glyph_info;
+ gint log_cluster;
+
+ glyph_info = glyphs->glyphs[i];
+ glyphs->glyphs[i] = glyphs->glyphs[j];
+ glyphs->glyphs[j] = glyph_info;
+
+ log_cluster = glyphs->log_clusters[i];
+ glyphs->log_clusters[i] = glyphs->log_clusters[j];
+ glyphs->log_clusters[j] = log_cluster;
+ }
+}
+
+
G_END_DECLS
#endif /* __PANGO_IMPL_UTILS_H__ */
-
diff --git a/pango/pango-ot-buffer.c b/pango/pango-ot-buffer.c
index a4aacc3a..533c3102 100644
--- a/pango/pango-ot-buffer.c
+++ b/pango/pango-ot-buffer.c
@@ -23,6 +23,7 @@
#include "pango-ot-private.h"
#include "pangofc-private.h"
+#include "pango-impl-utils.h"
/* cache a single hb_buffer_t */
static hb_buffer_t *cached_buffer = NULL;
@@ -204,26 +205,6 @@ pango_ot_buffer_get_glyphs (const PangoOTBuffer *buffer,
}
static void
-swap_range (PangoGlyphString *glyphs, int start, int end)
-{
- int i, j;
-
- for (i = start, j = end - 1; i < j; i++, j--)
- {
- PangoGlyphInfo glyph_info;
- gint log_cluster;
-
- glyph_info = glyphs->glyphs[i];
- glyphs->glyphs[i] = glyphs->glyphs[j];
- glyphs->glyphs[j] = glyph_info;
-
- log_cluster = glyphs->log_clusters[i];
- glyphs->log_clusters[i] = glyphs->log_clusters[j];
- glyphs->log_clusters[j] = log_cluster;
- }
-}
-
-static void
apply_gpos_ltr (PangoGlyphString *glyphs,
hb_glyph_position_t *positions,
gboolean is_hinted)
@@ -389,7 +370,7 @@ pango_ot_buffer_output (const PangoOTBuffer *buffer,
if (buffer->rtl)
{
/* Swap all glyphs */
- swap_range (glyphs, 0, glyphs->num_glyphs);
+ pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
}
positions = hb_buffer_get_glyph_positions (buffer->buffer);
diff --git a/pango/shape.c b/pango/shape.c
index 0dd56a8e..1513b028 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -108,20 +108,21 @@ pango_shape (const gchar *text,
else
glyphs->num_glyphs = 0;
- if (!glyphs->num_glyphs)
+ if (G_UNLIKELY (!glyphs->num_glyphs))
{
PangoEngineShape *fallback_engine = _pango_get_fallback_shaper ();
_pango_engine_shape_shape (fallback_engine, analysis->font,
text, length, analysis, glyphs);
+ if (G_UNLIKELY (!glyphs->num_glyphs))
+ return;
}
/* make sure last_cluster is invalid */
last_cluster = glyphs->log_clusters[0] - 1;
for (i = 0; i < glyphs->num_glyphs; i++)
{
- /* Set glyphs[i].attr.is_cluster_start based on log_clusters[]
- */
+ /* Set glyphs[i].attr.is_cluster_start based on log_clusters[] */
if (glyphs->log_clusters[i] != last_cluster)
{
glyphs->glyphs[i].attr.is_cluster_start = TRUE;
@@ -141,4 +142,31 @@ pango_shape (const gchar *text,
glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width;
}
}
+
+ /* Make sure glyphstring direction conforms to analysis->level */
+ if (G_UNLIKELY ((analysis->level & 1) &&
+ glyphs->log_clusters[0] < glyphs->log_clusters[glyphs->num_glyphs - 1]))
+ {
+ /* Warn once per shaper */
+ static GQuark warned_quark = 0;
+
+ if (!warned_quark)
+ warned_quark = g_quark_from_static_string ("pango-shape-warned");
+
+ if (analysis->shape_engine && !g_object_get_qdata (G_OBJECT (analysis->shape_engine), warned_quark))
+ {
+ GType engine_type = G_OBJECT_TYPE (analysis->shape_engine);
+ const char *engine_name = g_type_name (engine_type);
+ if (!engine_name)
+ engine_name = "(unknown)";
+
+ g_warning ("Expected RTL run but shape-engine='%s' returned LTR. Fixing.", engine_name);
+
+ g_object_set_qdata_full (G_OBJECT (analysis->shape_engine), warned_quark,
+ GINT_TO_POINTER (1), NULL);
+ }
+
+ /* *Fix* it so we don't crash later */
+ pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
+ }
}