< prev index next >

src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc

Print this page

        

@@ -67,10 +67,13 @@
                               const hb_feature_t             *user_features,
                               unsigned int                    num_user_features)
 {
   hb_ot_map_builder_t *map = &planner->map;
 
+  map->add_global_bool_feature (HB_TAG('r','v','r','n'));
+  map->add_gsub_pause (NULL);
+
   switch (props->direction) {
     case HB_DIRECTION_LTR:
       map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
       map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
       break;

@@ -161,23 +164,26 @@
  */
 
 hb_ot_shaper_shape_plan_data_t *
 _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
                                       const hb_feature_t *user_features,
-                                      unsigned int        num_user_features)
+                                      unsigned int        num_user_features,
+                                      const int          *coords,
+                                      unsigned int        num_coords)
 {
   hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
   if (unlikely (!plan))
     return NULL;
 
   hb_ot_shape_planner_t planner (shape_plan);
 
   planner.shaper = hb_ot_shape_complex_categorize (&planner);
 
-  hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
+  hb_ot_shape_collect_features (&planner, &shape_plan->props,
+                                user_features, num_user_features);
 
-  planner.compile (*plan);
+  planner.compile (*plan, coords, num_coords);
 
   if (plan->shaper->data_create) {
     plan->data = plan->shaper->data_create (plan);
     if (unlikely (!plan->data))
       return NULL;

@@ -210,10 +216,12 @@
   hb_buffer_t  *buffer;
   const hb_feature_t *user_features;
   unsigned int        num_user_features;
 
   /* Transient stuff */
+  bool fallback_positioning;
+  bool fallback_glyph_classes;
   hb_direction_t target_direction;
 };
 
 
 

@@ -522,10 +530,36 @@
 
   buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
 }
 
 static inline void
+hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
+{
+  unsigned int count = c->buffer->len;
+  hb_glyph_info_t *info = c->buffer->info;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    hb_ot_layout_glyph_props_flags_t klass;
+
+    /* Never mark default-ignorables as marks.
+     * They won't get in the way of lookups anyway,
+     * but having them as mark will cause them to be skipped
+     * over if the lookup-flag says so, but at least for the
+     * Mongolian variation selectors, looks like Uniscribe
+     * marks them as non-mark.  Some Mongolian fonts without
+     * GDEF rely on this.  Another notable character that
+     * this applies to is COMBINING GRAPHEME JOINER. */
+    klass = (_hb_glyph_info_get_general_category (&info[i]) !=
+             HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
+             _hb_glyph_info_is_default_ignorable (&info[i])) ?
+            HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
+            HB_OT_LAYOUT_GLYPH_PROPS_MARK;
+    _hb_glyph_info_set_glyph_props (&info[i], klass);
+  }
+}
+
+static inline void
 hb_ot_substitute_default (hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
   hb_ot_shape_initialize_masks (c);

@@ -537,11 +571,11 @@
   _hb_ot_shape_normalize (c->plan, buffer, c->font);
 
   hb_ot_shape_setup_masks (c);
 
   /* This is unfortunate to go here, but necessary... */
-  if (!hb_ot_layout_has_positioning (c->face))
+  if (c->fallback_positioning)
     _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
 
   hb_ot_map_glyphs_fast (buffer);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);

@@ -552,10 +586,13 @@
 {
   hb_buffer_t *buffer = c->buffer;
 
   hb_ot_layout_substitute_start (c->font, buffer);
 
+  if (!hb_ot_layout_has_glyph_classes (c->face))
+    hb_synthesize_glyph_classes (c);
+
   c->plan->substitute (c->font, buffer);
 
   return;
 }
 

@@ -630,30 +667,29 @@
   }
   if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
     _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
 }
 
-static inline bool
+static inline void
 hb_ot_position_complex (hb_ot_shape_context_t *c)
 {
   hb_ot_layout_position_start (c->font, c->buffer);
 
-  bool ret = false;
   unsigned int count = c->buffer->len;
-  bool has_positioning = (bool) hb_ot_layout_has_positioning (c->face);
 
   /* If the font has no GPOS, AND, no fallback positioning will
    * happen, AND, direction is forward, then when zeroing mark
    * widths, we shift the mark with it, such that the mark
    * is positioned hanging over the previous glyph.  When
    * direction is backward we don't shift and it will end up
    * hanging over the next glyph after the final reordering.
    * If fallback positinoing happens or GPOS is present, we don't
    * care.
    */
-  bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
-                                       HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
+  bool adjust_offsets_when_zeroing = c->fallback_positioning &&
+                                     !c->plan->shaper->fallback_position &&
+                                     HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
 
   switch (c->plan->shaper->zero_width_marks)
   {
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);

@@ -663,11 +699,11 @@
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
       break;
   }
 
-  if (has_positioning)
+  if (likely (!c->fallback_positioning))
   {
     hb_glyph_info_t *info = c->buffer->info;
     hb_glyph_position_t *pos = c->buffer->pos;
 
     /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */

@@ -686,11 +722,10 @@
       for (unsigned int i = 0; i < count; i++)
         c->font->subtract_glyph_h_origin (info[i].codepoint,
                                           &pos[i].x_offset,
                                           &pos[i].y_offset);
 
-    ret = true;
   }
 
   switch (c->plan->shaper->zero_width_marks)
   {
     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:

@@ -705,32 +740,30 @@
 
   /* Finishing off GPOS has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
   hb_ot_zero_width_default_ignorables (c);
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
-
-  return ret;
 }
 
 static inline void
 hb_ot_position (hb_ot_shape_context_t *c)
 {
   c->buffer->clear_positions ();
 
   hb_ot_position_default (c);
 
-  hb_bool_t fallback = !hb_ot_position_complex (c);
+  hb_ot_position_complex (c);
 
-  if (fallback && c->plan->shaper->fallback_position)
+  if (c->fallback_positioning && c->plan->shaper->fallback_position)
     _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
 
   if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
     hb_buffer_reverse (c->buffer);
 
   /* Visual fallback goes here. */
 
-  if (fallback)
+  if (c->fallback_positioning)
     _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
 
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
 }
 

@@ -746,10 +779,15 @@
   {
     c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_EXPANSION_FACTOR,
                               (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
 
+  bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
+  //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
+  c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
+  c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
+
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
 
   _hb_buffer_allocate_unicode_vars (c->buffer);
 
< prev index next >