Bug 635639 - Vowels are not rendered correctly in some Persian/Arabic/Hebrew fonts; r=jdaggett
authorJonathan Kew <jfkthame@gmail.com>
Wed, 23 Mar 2011 22:55:06 -0400
changeset 63780 a82e3f12c6217275e9ce0a0e359750b09fb9bdea
parent 63779 ff5717c3e48c19d2aebc30768ce1bde39e63b4d4
child 63781 cfe55d5089a94619f87c17ab989aeb47041ee1d3
push idunknown
push userunknown
push dateunknown
reviewersjdaggett
bugs635639
milestone2.2a1pre
Bug 635639 - Vowels are not rendered correctly in some Persian/Arabic/Hebrew fonts; r=jdaggett
gfx/harfbuzz/src/hb-ot-layout.cc
gfx/harfbuzz/src/hb-ot-layout.h
gfx/harfbuzz/src/hb-ot-shape.cc
--- a/gfx/harfbuzz/src/hb-ot-layout.cc
+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
@@ -28,16 +28,17 @@
 
 #define HB_OT_LAYOUT_CC
 
 #include "hb-ot-layout-private.hh"
 
 #include "hb-ot-layout-gdef-private.hh"
 #include "hb-ot-layout-gsub-private.hh"
 #include "hb-ot-layout-gpos-private.hh"
+#include "hb-ot-shape-private.hh"
 
 
 #include <stdlib.h>
 #include <string.h>
 
 HB_BEGIN_DECLS
 
 
@@ -471,15 +472,53 @@ hb_ot_layout_position_lookup   (hb_font_
 {
   hb_ot_layout_context_t c;
   c.font = font;
   c.face = face;
   return _get_gpos (face).position_lookup (&c, buffer, lookup_index, mask);
 }
 
 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_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_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);
 }
 
 
 HB_END_DECLS
--- a/gfx/harfbuzz/src/hb-ot-layout.h
+++ b/gfx/harfbuzz/src/hb-ot-layout.h
@@ -183,14 +183,14 @@ hb_bool_t
 hb_ot_layout_position_lookup (hb_font_t    *font,
 			      hb_face_t    *face,
 			      hb_buffer_t  *buffer,
 			      unsigned int  lookup_index,
 			      hb_mask_t     mask);
 
 /* 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
 
 #endif /* HB_OT_LAYOUT_H */
--- a/gfx/harfbuzz/src/hb-ot-shape.cc
+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
@@ -116,17 +116,17 @@ static void
 hb_ot_position_complex (hb_ot_shape_context_t *c)
 {
 
   if (!hb_ot_layout_has_positioning (c->face))
     return;
 
   c->plan->map.position (c->font, c->face, c->buffer);
 
-  hb_ot_layout_position_finish (c->buffer);
+  hb_ot_layout_position_finish (c->face, c->buffer);
 
   c->applied_position_complex = TRUE;
   return;
 }
 
 
 /* Main shaper */
 
@@ -255,19 +255,36 @@ hb_position_default (hb_ot_shape_context
   for (unsigned int i = 0; i < count; i++) {
     hb_font_get_glyph_advance (c->font, c->face, c->buffer->info[i].codepoint,
 			       &c->buffer->pos[i].x_advance,
 			       &c->buffer->pos[i].y_advance);
   }
 }
 
 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_CATEGORY_NON_SPACING_MARK)|(1<<HB_CATEGORY_ENCLOSING_MARK)|(1<<HB_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_CATEGORY_NON_SPACING_MARK)|(1<<HB_CATEGORY_ENCLOSING_MARK)|(1<<HB_CATEGORY_FORMAT))) {
+        hb_glyph_position_t& pos = c->buffer->pos[i];
+        pos.x_offset = -pos.x_advance;
+        pos.x_advance = 0;
+      }
+    }
+  }
 }
 
 static void
 hb_truetype_kern (hb_ot_shape_context_t *c)
 {
   /* TODO Check for kern=0 */
   unsigned int count = c->buffer->len;
   for (unsigned int i = 1; i < count; i++) {