bug 727736 - [harfbuzz] force glyphs for zero-width diacritics to actually have zero width, to work around bad fonts. r=behdad

This commit is contained in:
Jonathan Kew 2012-02-16 22:25:22 +00:00
parent fe86b1e34e
commit 34e53e353e
3 changed files with 65 additions and 5 deletions

View File

@ -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 <stdlib.h>
@ -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);
}

View File

@ -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

View File

@ -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<<gen_cat) & ((1<<HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)|
(1<<HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK)|
(1<<HB_UNICODE_GENERAL_CATEGORY_FORMAT))) {
c->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<<gen_cat) & ((1<<HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)|
(1<<HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK)|
(1<<HB_UNICODE_GENERAL_CATEGORY_FORMAT))) {
hb_glyph_position_t& pos = c->buffer->pos[i];
pos.x_offset = -pos.x_advance;
pos.x_advance = 0;
}
}
}
}
static void