Imported Upstream version 0.9.12
[platform/upstream/harfbuzz.git] / src / hb-graphite2.cc
index a30c42e..16ef9a4 100644 (file)
@@ -113,7 +113,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face)
     hb_blob_destroy (silf_blob);
 
   data->face = face;
-  data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_default);
+  data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
 
   if (unlikely (!data->grface)) {
     free (data);
@@ -141,6 +141,13 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
   free (data);
 }
 
+gr_face *
+hb_graphite2_face_get_gr_face (hb_face_t *face)
+{
+  if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return NULL;
+  return HB_SHAPER_DATA_GET (face)->grface;
+}
+
 
 /*
  * shaper font data
@@ -168,6 +175,13 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
   gr_font_destroy (data);
 }
 
+gr_font *
+hb_graphite2_font_get_gr_font (hb_font_t *font)
+{
+  if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL;
+  return HB_SHAPER_DATA_GET (font);
+}
+
 
 /*
  * shaper shape_plan data
@@ -211,11 +225,6 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
   gr_font *grfont = HB_SHAPER_DATA_GET (font);
 
-  unsigned int charlen;
-  hb_glyph_info_t *bufferi = hb_buffer_get_glyph_infos (buffer, &charlen);
-
-  int success = 0;
-
   const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
   const char *lang_end = strchr (lang, '-');
   int lang_len = lang_end ? lang_end - lang : -1;
@@ -229,24 +238,23 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
     features++;
   }
 
-  /* TODO Use scratch buffer for these. */
-  hb_codepoint_t *gids = NULL, *pg;
-  hb_graphite2_cluster_t *clusters = NULL;
   gr_segment *seg = NULL;
-  uint32_t *text = NULL;
   const gr_slot *is;
   unsigned int ci = 0, ic = 0;
   float curradvx = 0., curradvy = 0.;
-  unsigned int glyphlen = 0;
-  unsigned int *p;
 
-  text = (uint32_t *) malloc ((charlen + 1) * sizeof (uint32_t));
-  if (!text) goto dieout;
+  unsigned int scratch_size;
+  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+
+#define ALLOCATE_ARRAY(Type, name, len) \
+  Type *name = (Type *) scratch; \
+  scratch += (len) * sizeof ((name)[0]); \
+  scratch_size -= (len) * sizeof ((name)[0]);
 
-  p = text;
-  for (unsigned int i = 0; i < charlen; ++i)
-    *p++ = bufferi++->codepoint;
-  *p = 0;
+  ALLOCATE_ARRAY (uint32_t, chars, buffer->len);
+
+  for (unsigned int i = 0; i < buffer->len; ++i)
+    chars[i] = buffer->info[i].codepoint;
 
   hb_tag_t script_tag[2];
   hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
@@ -254,18 +262,40 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   seg = gr_make_seg (grfont, grface,
                     script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
                     feats,
-                    gr_utf32, text, charlen,
+                    gr_utf32, chars, buffer->len,
                     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
-  if (!seg) goto dieout;
 
-  glyphlen = gr_seg_n_slots (seg);
-  clusters = (hb_graphite2_cluster_t *) calloc (charlen, sizeof (hb_graphite2_cluster_t));
-  if (!glyphlen || !clusters) goto dieout;
+  if (unlikely (!seg)) {
+    if (feats) gr_featureval_destroy (feats);
+    return false;
+  }
+
+  unsigned int glyph_count = gr_seg_n_slots (seg);
+  if (unlikely (!glyph_count)) {
+    if (feats) gr_featureval_destroy (feats);
+    gr_seg_destroy (seg);
+    return false;
+  }
+
+  scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+  while ((sizeof (hb_graphite2_cluster_t) * buffer->len +
+         sizeof (hb_codepoint_t) * glyph_count) > scratch_size)
+  {
+    buffer->ensure (buffer->allocated * 2);
+    if (unlikely (buffer->in_error)) {
+      if (feats) gr_featureval_destroy (feats);
+      gr_seg_destroy (seg);
+      return false;
+    }
+    scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
+  }
+
+  ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
+  ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
 
-  gids = (hb_codepoint_t *) malloc (glyphlen * sizeof (hb_codepoint_t));
-  if (!gids) goto dieout;
+  memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
 
-  pg = gids;
+  hb_codepoint_t *pg = gids;
   for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
   {
     unsigned int before = gr_slot_before (is);
@@ -295,10 +325,18 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   }
   ci++;
 
-  buffer->clear_output ();
+  //buffer->clear_output ();
   for (unsigned int i = 0; i < ci; ++i)
-    buffer->replace_glyphs (clusters[i].num_chars, clusters[i].num_glyphs, gids + clusters[i].base_glyph);
-  buffer->swap_buffers ();
+  {
+    for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j)
+    {
+      hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
+      info->codepoint = gids[clusters[i].base_glyph + j];
+      info->cluster = gr_cinfo_base(gr_seg_cinfo(seg, clusters[i].base_char));
+    }
+  }
+  buffer->len = glyph_count;
+  //buffer->swap_buffers ();
 
   if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
     curradvx = gr_seg_advance_X(seg);
@@ -325,13 +363,8 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
     hb_buffer_reverse_clusters (buffer);
 
-  success = 1;
-
-dieout:
   if (feats) gr_featureval_destroy (feats);
-  if (gids) free (gids);
-  if (clusters) free (clusters);
-  if (seg) gr_seg_destroy (seg);
-  if (text) free (text);
-  return success;
+  gr_seg_destroy (seg);
+
+  return true;
 }