19c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/***************************************************************************/
29c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*                                                                         */
39c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  hbshim.c                                                               */
49c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*                                                                         */
59c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*    HarfBuzz interface for accessing OpenType features (body).           */
69c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*                                                                         */
79c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  Copyright 2013, 2014 by                                                */
89c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
99c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*                                                                         */
109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  This file is part of the FreeType project, and may only be used,       */
119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  modified, and distributed under the terms of the FreeType project      */
129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  this file you indicate that you have read the license and              */
149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*  understand and accept it fully.                                        */
159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/*                                                                         */
169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/***************************************************************************/
179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include <ft2build.h>
209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include FT_FREETYPE_H
219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afglobal.h"
229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "aftypes.h"
239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "hbshim.h"
249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /*************************************************************************/
299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /*                                                                       */
309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* messages during execution.                                            */
339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /*                                                                       */
349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#undef  FT_COMPONENT
359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define FT_COMPONENT  trace_afharfbuzz
369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /*
399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   * We use `sets' (in the HarfBuzz sense, which comes quite near to the
409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   * usual mathematical meaning) to manage both lookups and glyph indices.
419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *
429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   * 1. For each coverage, collect lookup IDs in a set.  Note that an
439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    auto-hinter `coverage' is represented by one `feature', and a
449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    feature consists of an arbitrary number of (font specific) `lookup's
459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    that actually do the mapping job.  Please check the OpenType
469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    specification for more details on features and lookups.
479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *
489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   * 2. Create glyph ID sets from the corresponding lookup sets.
499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *
509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   * 3. The glyph set corresponding to AF_COVERAGE_DEFAULT is computed
519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    with all lookups specific to the OpenType script activated.  It
529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    relies on the order of AF_DEFINE_STYLE_CLASS entries so that
539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *    special coverages (like `oldstyle figures') don't get overwritten.
549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   *
559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod   */
569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* load coverage tags */
599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#undef  COVERAGE
609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define COVERAGE( name, NAME, description,             \
619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                  tag1, tag2, tag3, tag4 )             \
629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          static const hb_tag_t  name ## _coverage[] = \
639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          {                                            \
649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            HB_TAG( tag1, tag2, tag3, tag4 ),          \
659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            HB_TAG_NONE                                \
669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          };
679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afcover.h"
709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* define mapping between coverage tags and AF_Coverage */
739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#undef  COVERAGE
749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define COVERAGE( name, NAME, description, \
759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                  tag1, tag2, tag3, tag4 ) \
769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          name ## _coverage,
779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  static const hb_tag_t*  coverages[] =
809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afcover.h"
829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    NULL /* AF_COVERAGE_DEFAULT */
849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  };
859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* load HarfBuzz script tags */
889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#undef  SCRIPT
899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define SCRIPT( s, S, d, h, sc1, sc2, sc3 )  h,
909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  static const hb_script_t  scripts[] =
939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afscript.h"
959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  };
969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  FT_Error
999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_get_coverage( AF_FaceGlobals  globals,
1009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                   AF_StyleClass   style_class,
1019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                   FT_Byte*        gstyles )
1029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
1039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_face_t*  face;
1049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_t*  gsub_lookups;  /* GSUB lookups for a given script */
1069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_t*  gsub_glyphs;   /* glyphs covered by GSUB lookups  */
1079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_t*  gpos_lookups;  /* GPOS lookups for a given script */
1089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_t*  gpos_glyphs;   /* glyphs covered by GPOS lookups  */
1099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_script_t      script;
1119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    const hb_tag_t*  coverage_tags;
1129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_tag_t         script_tags[] = { HB_TAG_NONE,
1139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                       HB_TAG_NONE,
1149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                       HB_TAG_NONE,
1159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                       HB_TAG_NONE };
1169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_codepoint_t  idx;
1189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
1199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    int             count;
1209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
1219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( !globals || !style_class || !gstyles )
1249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      return FT_THROW( Invalid_Argument );
1259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    face = hb_font_get_face( globals->hb_font );
1279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    gsub_lookups = hb_set_create();
1299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    gsub_glyphs  = hb_set_create();
1309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    gpos_lookups = hb_set_create();
1319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    gpos_glyphs  = hb_set_create();
1329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    coverage_tags = coverages[style_class->coverage];
1349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    script        = scripts[style_class->script];
1359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /* Convert a HarfBuzz script tag into the corresponding OpenType */
1379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /* tag or tags -- some Indic scripts like Devanagari have an old */
1389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /* and a new set of features.                                    */
1399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_ot_tags_from_script( script,
1409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                            &script_tags[0],
1419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                            &script_tags[1] );
1429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
1449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /* as the second tag.  We change that to HB_TAG_NONE except for the  */
1459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /* default script.                                                   */
1469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( style_class->script == globals->module->default_script &&
1479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod         style_class->coverage == AF_COVERAGE_DEFAULT           )
1489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
1499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( script_tags[0] == HB_TAG_NONE )
1509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        script_tags[0] = HB_OT_TAG_DEFAULT_SCRIPT;
1519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      else
1529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      {
1539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        if ( script_tags[1] == HB_TAG_NONE )
1549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          script_tags[1] = HB_OT_TAG_DEFAULT_SCRIPT;
1559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        else if ( script_tags[1] != HB_OT_TAG_DEFAULT_SCRIPT )
1569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          script_tags[2] = HB_OT_TAG_DEFAULT_SCRIPT;
1579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      }
1589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
1599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
1609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
1619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
1629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        script_tags[1] = HB_TAG_NONE;
1639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
1649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_ot_layout_collect_lookups( face,
1669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  HB_OT_TAG_GSUB,
1679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  script_tags,
1689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  NULL,
1699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  coverage_tags,
1709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  gsub_lookups );
1719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( hb_set_is_empty( gsub_lookups ) )
1739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      goto Exit; /* nothing to do */
1749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_ot_layout_collect_lookups( face,
1769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  HB_OT_TAG_GPOS,
1779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  script_tags,
1789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  NULL,
1799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  coverage_tags,
1809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                  gpos_lookups );
1819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_TRACE4(( "GSUB lookups (style `%s'):\n"
1839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                " ",
1849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                af_style_names[style_class->style] ));
1859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
1879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    count = 0;
1889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
1899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    for ( idx = -1; hb_set_next( gsub_lookups, &idx ); )
1919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
1929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
1939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_TRACE4(( " %d", idx ));
1949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      count++;
1959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
1969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
1979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* get output coverage of GSUB feature */
1989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_ot_layout_lookup_collect_glyphs( face,
1999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          HB_OT_TAG_GSUB,
2009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          idx,
2019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          NULL,
2029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          NULL,
2039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          NULL,
2049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          gsub_glyphs );
2059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
2069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
2089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( !count )
2099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_TRACE4(( " (none)" ));
2109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_TRACE4(( "\n\n" ));
2119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
2129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_TRACE4(( "GPOS lookups (style `%s'):\n"
2149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                " ",
2159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                af_style_names[style_class->style] ));
2169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
2189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    count = 0;
2199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
2209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    for ( idx = -1; hb_set_next( gpos_lookups, &idx ); )
2229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
2239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
2249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_TRACE4(( " %d", idx ));
2259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      count++;
2269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
2279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* get input coverage of GPOS feature */
2299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_ot_layout_lookup_collect_glyphs( face,
2309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          HB_OT_TAG_GPOS,
2319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          idx,
2329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          NULL,
2339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          gpos_glyphs,
2349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          NULL,
2359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                          NULL );
2369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
2379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
2399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( !count )
2409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_TRACE4(( " (none)" ));
2419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_TRACE4(( "\n\n" ));
2429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
2439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /*
2459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * We now check whether we can construct blue zones, using glyphs
2469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * covered by the feature only.  In case there is not a single zone
2479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * (this is, not a single character is covered), we skip this coverage.
2489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
2499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     */
2509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( style_class->coverage != AF_COVERAGE_DEFAULT )
2519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
2529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      AF_Blue_Stringset         bss = style_class->blue_stringset;
2539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      const AF_Blue_StringRec*  bs  = &af_blue_stringsets[bss];
2549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_Bool  found = 0;
2569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
2599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      {
2609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        const char*  p = &af_blue_strings[bs->string];
2619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        while ( *p )
2649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        {
2659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          hb_codepoint_t  ch;
2669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          GET_UTF8_CHAR( ch, p );
2699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          for ( idx = -1; hb_set_next( gsub_lookups, &idx ); )
2719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          {
2729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            hb_codepoint_t  gidx = FT_Get_Char_Index( globals->face, ch );
2739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            if ( hb_ot_layout_lookup_would_substitute( face, idx,
2769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                                                       &gidx, 1, 1 ) )
2779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {
2789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              found = 1;
2799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              break;
2809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }
2819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          }
2829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        }
2839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      }
2849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( !found )
2869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      {
2879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_TRACE4(( "  no blue characters found; style skipped\n" ));
2889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        goto Exit;
2899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      }
2909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
2919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
2929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    /*
2939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * Various OpenType features might use the same glyphs at different
2949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * vertical positions; for example, superscript and subscript glyphs
2959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * could be the same.  However, the auto-hinter is completely
2969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * agnostic of OpenType features after the feature analysis has been
2979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * completed: The engine then simply receives a glyph index and returns a
2989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * hinted and usually rendered glyph.
2999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * Consider the superscript feature of font `pala.ttf': Some of the
3019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * glyphs are `real', this is, they have a zero vertical offset, but
3029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * most of them are small caps glyphs shifted up to the superscript
3039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * position (this is, the `sups' feature is present in both the GSUB and
3049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * GPOS tables).  The code for blue zones computation actually uses a
3059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * feature's y offset so that the `real' glyphs get correct hints.  But
3069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * later on it is impossible to decide whether a glyph index belongs to,
3079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * say, the small caps or superscript feature.
3089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * For this reason, we don't assign a style to a glyph if the current
3109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * feature covers the glyph in both the GSUB and the GPOS tables.  This
3119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * is quite a broad condition, assuming that
3129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *   (a) glyphs that get used in multiple features are present in a
3149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *       feature without vertical shift,
3159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * and
3179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *   (b) a feature's GPOS data really moves the glyph vertically.
3199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * Not fulfilling condition (a) makes a font larger; it would also
3219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * reduce the number of glyphs that could be addressed directly without
3229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * using OpenType features, so this assumption is rather strong.
3239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * Condition (b) is much weaker, and there might be glyphs which get
3259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * missed.  However, the OpenType features we are going to handle are
3269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * primarily located in GSUB, and HarfBuzz doesn't provide an API to
3279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * directly get the necessary information from the GPOS table.  A
3289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * possible solution might be to directly parse the GPOS table to find
3299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * out whether a glyph gets shifted vertically, but this is something I
3309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * would like to avoid if not really necessary.
3319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * Note that we don't follow this logic for the default coverage.
3339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * Complex scripts like Devanagari have mandatory GPOS features to
3349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * position many glyph elements, using mark-to-base or mark-to-ligature
3359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * tables; the number of glyphs missed due to condition (b) would be far
3369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     * too large.
3379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     *
3389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod     */
3399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( style_class->coverage != AF_COVERAGE_DEFAULT )
3409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_set_subtract( gsub_glyphs, gpos_glyphs );
3419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
3439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_TRACE4(( "  glyphs without GPOS data (`*' means already assigned)" ));
3449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    count = 0;
3459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
3469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    for ( idx = -1; hb_set_next( gsub_glyphs, &idx ); )
3489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
3499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
3509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( !( count % 10 ) )
3519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_TRACE4(( "\n"
3529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                    "   " ));
3539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_TRACE4(( " %d", idx ));
3559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      count++;
3569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
3579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */
3599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* can be arbitrary: some fonts use fake indices for processing   */
3609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* internal to GSUB or GPOS, which is fully valid                 */
3619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( idx >= (hb_codepoint_t)globals->glyph_count )
3629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        continue;
3639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
3659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        gstyles[idx] = (FT_Byte)style_class->style;
3669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
3679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      else
3689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_TRACE4(( "*" ));
3699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
3709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
3719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
3739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( !count )
3749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_TRACE4(( "\n"
3759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                  "    (none)" ));
3769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_TRACE4(( "\n\n" ));
3779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
3789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  Exit:
3809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_destroy( gsub_lookups );
3819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_destroy( gsub_glyphs  );
3829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_destroy( gpos_lookups );
3839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    hb_set_destroy( gpos_glyphs  );
3849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    return FT_Err_Ok;
3869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  }
3879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
3899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* construct HarfBuzz features */
3909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#undef  COVERAGE
3919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define COVERAGE( name, NAME, description,                \
3929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                  tag1, tag2, tag3, tag4 )                \
3939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          static const hb_feature_t  name ## _feature[] = \
3949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          {                                               \
3959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            {                                             \
3969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              HB_TAG( tag1, tag2, tag3, tag4 ),           \
3979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod              1, 0, (unsigned int)-1                      \
3989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod            }                                             \
3999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          };
4009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afcover.h"
4039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  /* define mapping between HarfBuzz features and AF_Coverage */
4069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#undef  COVERAGE
4079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define COVERAGE( name, NAME, description, \
4089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                  tag1, tag2, tag3, tag4 ) \
4099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod          name ## _feature,
4109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  static const hb_feature_t*  features[] =
4139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
4149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afcover.h"
4159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    NULL /* AF_COVERAGE_DEFAULT */
4179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  };
4189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  FT_Error
4219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_get_char_index( AF_StyleMetrics  metrics,
4229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                     FT_ULong         charcode,
4239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                     FT_ULong        *codepoint,
4249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                     FT_Long         *y_offset )
4259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
4269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    AF_StyleClass  style_class;
4279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    const hb_feature_t*  feature;
4299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_ULong  in_idx, out_idx;
4319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( !metrics )
4349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      return FT_THROW( Invalid_Argument );
4359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    in_idx = FT_Get_Char_Index( metrics->globals->face, charcode );
4379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    style_class = metrics->style_class;
4399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    feature = features[style_class->coverage];
4419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( feature )
4439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
4449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      FT_UInt  upem = metrics->globals->face->units_per_EM;
4459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_font_t*    font = metrics->globals->hb_font;
4479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_buffer_t*  buf  = hb_buffer_create();
4489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      uint32_t  c = (uint32_t)charcode;
4509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4519c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_glyph_info_t*      ginfo;
4529c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_glyph_position_t*  gpos;
4539c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      unsigned int          gcount;
4549c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4559c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4569c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* we shape at a size of units per EM; this means font units */
4579c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_font_set_scale( font, upem, upem );
4589c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4599c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* XXX: is this sufficient for a single character of any script? */
4609c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_buffer_set_direction( buf, HB_DIRECTION_LTR );
4619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_buffer_set_script( buf, scripts[style_class->script] );
4629c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4639c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* we add one character to `buf' ... */
4649c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_buffer_add_utf32( buf, &c, 1, 0, 1 );
4659c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* ... and apply one feature */
4679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_shape( font, buf, feature, 1 );
4689c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4699c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
4709c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      gpos  = hb_buffer_get_glyph_positions( buf, &gcount );
4719c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4729c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      out_idx = ginfo[0].codepoint;
4739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4749c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* getting the same index indicates no substitution,         */
4759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      /* which means that the glyph isn't available in the feature */
4769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( in_idx == out_idx )
4779c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      {
4789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        *codepoint = 0;
4799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        *y_offset  = 0;
4809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      }
4819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      else
4829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      {
4839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        *codepoint = out_idx;
4849c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        *y_offset  = gpos[0].y_offset;
4859c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      }
4869c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4879c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      hb_buffer_destroy( buf );
4889c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
4899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE
4909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      if ( gcount > 1 )
4919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod        FT_TRACE1(( "af_get_char_index:"
4929c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                    " input character mapped to multiple glyphs\n" ));
4939c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif
4949c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
4959c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    else
4969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    {
4979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *codepoint = in_idx;
4989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      *y_offset  = 0;
4999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    }
5009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    return FT_Err_Ok;
5029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  }
5039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
5069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  FT_Error
5099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_get_coverage( AF_FaceGlobals  globals,
5109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                   AF_StyleClass   style_class,
5119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                   FT_Byte*        gstyles )
5129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
5139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_UNUSED( globals );
5149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_UNUSED( style_class );
5159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_UNUSED( gstyles );
5169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    return FT_Err_Ok;
5189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  }
5199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  FT_Error
5229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  af_get_char_index( AF_StyleMetrics  metrics,
5239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                     FT_ULong         charcode,
5249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                     FT_ULong        *codepoint,
5259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod                     FT_Long         *y_offset )
5269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  {
5279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    FT_Face  face;
5289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    if ( !metrics )
5319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod      return FT_THROW( Invalid_Argument );
5329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    face = metrics->globals->face;
5349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    *codepoint = FT_Get_Char_Index( face, charcode );
5369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    *y_offset  = 0;
5379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod    return FT_Err_Ok;
5399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod  }
5409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
5439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
5459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/* END */
546