diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2009-11-17 16:20:42 -0500 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2009-11-17 16:21:11 -0500 |
commit | 4ccabeffc20f899163bf610356871afb197e9bf8 (patch) | |
tree | 629478f89f68fc763f55cbc53bd8d1d25160c610 /pango | |
parent | 718c533d28cb760e45c7b874420b14003445a9c1 (diff) | |
download | pango-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.
Diffstat (limited to 'pango')
-rw-r--r-- | pango/glyphstring.c | 2 | ||||
-rw-r--r-- | pango/pango-engine.c | 3 | ||||
-rw-r--r-- | pango/pango-impl-utils.h | 26 | ||||
-rw-r--r-- | pango/pango-ot-buffer.c | 23 | ||||
-rw-r--r-- | pango/shape.c | 34 |
5 files changed, 61 insertions, 27 deletions
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); + } } |