15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2011  Martin Hosken
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2011  SIL International
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2011,2012  Google, Inc.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_SHAPER graphite2
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define hb_graphite2_shaper_font_data_t gr_font
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-shaper-impl-private.hh"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-graphite2.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <graphite2/Segment.h>
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper face data
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct hb_graphite2_tablelist_t {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct hb_graphite2_tablelist_t *next;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *blob;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int tag;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} hb_graphite2_tablelist_t;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_graphite2_shaper_face_data_t {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_face   *grface;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_graphite2_tablelist_t *tlist;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_graphite2_tablelist_t *tlist = face_data->tlist;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *blob = NULL;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (hb_graphite2_tablelist_t *p = tlist; p; p = p->next)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (p->tag == tag) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blob = p->blob;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!blob))
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blob = face_data->face->reference_table (tag);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t));
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!p)) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_blob_destroy (blob);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->blob = blob;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->tag = tag;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO Not thread-safe, but fairly harmless.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * We can do the double-chcked pointer cmpexch thing here. */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->next = face_data->tlist;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    face_data->tlist = p;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int tlen;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *d = hb_blob_get_data (blob, &tlen);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *len = tlen;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return d;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_graphite2_shaper_face_data_t *
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shaper_face_data_create (hb_face_t *face)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Umm, we just reference the table to check whether it exists.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Maybe add better API for this? */
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!hb_blob_get_length (silf_blob))
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_destroy (silf_blob);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_destroy (silf_blob);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!data))
11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return NULL;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->face = face;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!data->grface)) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free (data);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_graphite2_tablelist_t *tlist = data->tlist;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (tlist)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_graphite2_tablelist_t *old = tlist;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_blob_destroy (tlist->blob);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tlist = tlist->next;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free (old);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_face_destroy (data->grface);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free (data);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gr_face *
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_graphite2_face_get_gr_face (hb_face_t *face)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return NULL;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return HB_SHAPER_DATA_GET (face)->grface;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper font data
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_graphite2_shaper_font_data_t *
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shaper_font_data_create (hb_font_t *font)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face = font->face;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_font_destroy (data);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gr_font *
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_graphite2_font_get_gr_font (hb_font_t *font)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return HB_SHAPER_DATA_GET (font);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper shape_plan data
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_graphite2_shaper_shape_plan_data_t {};
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_graphite2_shaper_shape_plan_data_t *
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     const hb_feature_t *user_features HB_UNUSED,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     unsigned int        num_user_features HB_UNUSED)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_graphite2_cluster_t {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int base_char;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int num_chars;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int base_glyph;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int num_glyphs;
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  unsigned int cluster;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     hb_font_t          *font,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     hb_buffer_t        *buffer,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const hb_feature_t *features,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     unsigned int        num_features)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face = font->face;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_font *grfont = HB_SHAPER_DATA_GET (font);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char *lang_end = lang ? strchr (lang, '-') : NULL;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lang_len = lang_end ? lang_end - lang : -1;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (num_features--)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gr_feature_ref *fref = gr_face_find_fref (grface, features->tag);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fref)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gr_fref_set_feature_value (fref, features->value, feats);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    features++;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_segment *seg = NULL;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gr_slot *is;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int ci = 0, ic = 0;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float curradvx = 0., curradvy = 0.;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int scratch_size;
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  uint32_t *chars = (uint32_t *) scratch;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < buffer->len; ++i)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chars[i] = buffer->info[i].codepoint;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_tag_t script_tag[2];
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  seg = gr_make_seg (grfont, grface,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     feats,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     gr_utf32, chars, buffer->len,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!seg)) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (feats) gr_featureval_destroy (feats);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int glyph_count = gr_seg_n_slots (seg);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!glyph_count)) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (feats) gr_featureval_destroy (feats);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gr_seg_destroy (seg);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scratch = buffer->get_scratch_buffer (&scratch_size);
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) +
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (unlikely (!buffer->ensure (buffer->allocated * 2)))
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (feats) gr_featureval_destroy (feats);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gr_seg_destroy (seg);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scratch = buffer->get_scratch_buffer (&scratch_size);
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define ALLOCATE_ARRAY(Type, name, len) \
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Type *name = (Type *) scratch; \
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  { \
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    assert (_consumed <= scratch_size); \
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scratch += _consumed; \
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scratch_size -= _consumed; \
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#undef ALLOCATE_ARRAY
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_codepoint_t *pg = gids;
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  clusters[0].cluster = buffer->info[0].cluster;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int before = gr_slot_before (is);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int after = gr_slot_after (is);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pg = gr_slot_gid (is);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pg++;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (clusters[ci].base_char > before && ci)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clusters[ci-1].num_chars += clusters[ci].num_chars;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clusters[ci-1].num_glyphs += clusters[ci].num_glyphs;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ci--;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= clusters[ci].base_char + clusters[ci].num_chars)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hb_graphite2_cluster_t *c = clusters + ci + 1;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->base_char = clusters[ci].base_char + clusters[ci].num_chars;
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      c->cluster = buffer->info[c->base_char].cluster;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->num_chars = before - c->base_char;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->base_glyph = ic;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c->num_glyphs = 0;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ci++;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clusters[ci].num_glyphs++;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (clusters[ci].base_char + clusters[ci].num_chars < after + 1)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ci++;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //buffer->clear_output ();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < ci; ++i)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info->codepoint = gids[clusters[i].base_glyph + j];
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      info->cluster = clusters[i].cluster;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer->len = glyph_count;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //buffer->swap_buffers ();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curradvx = gr_seg_advance_X(seg);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_glyph_position_t *pPos;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       is; pPos++, is = gr_slot_next_in_segment (is))
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos->x_offset = gr_slot_origin_X (is) - curradvx;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curradvx -= pPos->x_advance;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos->x_offset = gr_slot_origin_X (is) - curradvx;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curradvx += pPos->x_advance;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curradvy += pPos->y_advance;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_buffer_reverse_clusters (buffer);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (feats) gr_featureval_destroy (feats);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gr_seg_destroy (seg);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
377