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