From a316d01212d5869be4b2f8707324351c05edba01 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 16 Feb 2012 22:25:22 +0000 Subject: [PATCH] bug 727736 - [harfbuzz] force glyphs for zero-width diacritics to actually have zero width, to work around bad fonts. r=behdad --- gfx/harfbuzz/src/hb-ot-layout.cc | 41 +++++++++++++++++++++++++++++++- gfx/harfbuzz/src/hb-ot-layout.h | 2 +- gfx/harfbuzz/src/hb-ot-shape.cc | 27 ++++++++++++++++++--- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc index f3e07139adb..bfbe890b4ab 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.cc +++ b/gfx/harfbuzz/src/hb-ot-layout.cc @@ -32,6 +32,7 @@ #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-maxp-table.hh" +#include "hb-ot-shape-private.hh" #include @@ -496,8 +497,46 @@ hb_ot_layout_position_lookup (hb_font_t *font, } void -hb_ot_layout_position_finish (hb_buffer_t *buffer) +hb_ot_layout_position_finish (hb_face_t *face, hb_buffer_t *buffer) { + /* force diacritics to have zero width */ + unsigned int count = buffer->len; + if (hb_ot_layout_has_glyph_classes (face)) { + const GDEF& gdef = _get_gdef (face); + if (buffer->props.direction == HB_DIRECTION_RTL) { + for (unsigned int i = 1; i < count; i++) { + if (gdef.get_glyph_class (buffer->info[i].codepoint) == GDEF::MarkGlyph) { + buffer->pos[i].x_advance = 0; + } + } + } else { + for (unsigned int i = 1; i < count; i++) { + if (gdef.get_glyph_class (buffer->info[i].codepoint) == GDEF::MarkGlyph) { + hb_glyph_position_t& pos = buffer->pos[i]; + pos.x_offset -= pos.x_advance; + pos.x_advance = 0; + } + } + } + } else { + /* no GDEF classes available, so use General Category as a fallback */ + if (buffer->props.direction == HB_DIRECTION_RTL) { + for (unsigned int i = 1; i < count; i++) { + if (buffer->info[i].general_category() == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + buffer->pos[i].x_advance = 0; + } + } + } else { + for (unsigned int i = 1; i < count; i++) { + if (buffer->info[i].general_category() == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { + hb_glyph_position_t& pos = buffer->pos[i]; + pos.x_offset -= pos.x_advance; + pos.x_advance = 0; + } + } + } + } + GPOS::position_finish (buffer); } diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h index 447e35dbfad..96f25722dea 100644 --- a/gfx/harfbuzz/src/hb-ot-layout.h +++ b/gfx/harfbuzz/src/hb-ot-layout.h @@ -199,7 +199,7 @@ hb_ot_layout_position_lookup (hb_font_t *font, /* Should be called after all the position_lookup's are done */ void -hb_ot_layout_position_finish (hb_buffer_t *buffer); +hb_ot_layout_position_finish (hb_face_t *face, hb_buffer_t *buffer); HB_END_DECLS diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc index 4275afc8251..09db9125cbe 100644 --- a/gfx/harfbuzz/src/hb-ot-shape.cc +++ b/gfx/harfbuzz/src/hb-ot-shape.cc @@ -299,15 +299,36 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) c->applied_position_complex = TRUE; } - hb_ot_layout_position_finish (c->buffer); + hb_ot_layout_position_finish (c->face, c->buffer); return; } static void -hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED) +hb_position_complex_fallback (hb_ot_shape_context_t *c) { - /* TODO Mark pos */ + unsigned int count = c->buffer->len; + if (c->buffer->props.direction == HB_DIRECTION_RTL) { + for (unsigned int i = 1; i < count; i++) { + unsigned int gen_cat = c->buffer->info[i].general_category(); + if ((1<buffer->pos[i].x_advance = 0; + } + } + } else { + for (unsigned int i = 1; i < count; i++) { + unsigned int gen_cat = c->buffer->info[i].general_category(); + if ((1<buffer->pos[i]; + pos.x_offset = -pos.x_advance; + pos.x_advance = 0; + } + } + } } static void